Instituto Tecnológico Superior de Huatusco
Docente: MSC. Olivia Labastida Puertos Tema 2: Modelo de Programación Funcional E-mail: olabastidap@huatusco.tecnm.mx
Competencia Específica: Realiza una aplicación dando solución a un problema del entorno usando el paradigma de la programación funcional.
2.1 Introducción al modelo de programación funcional
La programación funcional, o mejor dicho, los lenguajes de programación funcionales, son aquellos lenguajes donde las variables no tienen estado, no hay cambios en éstas a lo largo del tiempo y son inmutables, no pueden cambiarse los valores a lo largo de la ejecución.
2.1 Introducción al modelo de programación funcional
Además los programas se estructuran componiendo expresiones que se evalúan como funciones. Dentro de los lenguajes funcionales tenemos Lisp, Scheme, Clojure, Haskell, OCaml y Standard ML, entre otros. Estos lenguajes están diversidad de tipificación, donde se encuentran lenguajes dinámicos, estáticos y estáticos fuertes.
2.1 El tipo de datos
Es un atributo de una parte de los datos que indica al ordenador (y/o al programador) algo sobre la clase de datos sobre los que se va a procesar. Esto incluye imponer restricciones en los datos, como qué valores pueden tomar y qué operaciones se pueden realizar. Tipos de datos comunes son: enteros, números de coma flotante (decimales), cadenas alfanuméricas, fechas, horas, colores, etc.
2.1 El tipo de datos
Por ejemplo, por lo general el tipo "int" representa un conjunto de enteros de 32 bits cuyo rango va desde el -2.147.483.648 al 2.147.483.647, así como las operaciones que se pueden realizar con los enteros, como son la suma, la resta, y la multiplicación.
2.1 El tipo de datos
Los colores, por su parte, se representan como tres bytes denotando la cantidad de rojo, verde y azul, y una cadena de caracteres representando el nombre del color; las operaciones permitidas en este caso incluyen la adición y la sustracción, pero no la multiplicación.
2.1 El tipo de datos
Éste es un concepto propio de la informática, más específicamente de los lenguajes de programación, aunque también se encuentra relacionado con nociones similares de la matemática y la lógica.
2.1 El tipo de datos
En un sentido amplio, un tipo de datos define un conjunto de valores y las operaciones sobre estos valores. Casi todos los lenguajes de programación explícitamente incluyen la notación del tipo de datos, aunque lenguajes diferentes pueden usar terminologías diferentes.
2.1 El tipo de datos
La mayor parte de los lenguajes de programación permiten al programador definir tipos de datos adicionales, normalmente combinando múltiples elementos de otros tipos y definiendo las operaciones del nuevo tipo de dato.
2.1 El tipo de datos
Por ejemplo, un programador puede crear un nuevo tipo de dato llamado "Persona" que específica que el dato interpretado como Persona incluirá, por ejemplo, un nombre y una fecha de nacimiento.
2.1 El tipo de datos
Un tipo de dato puede ser también visto como una limitación impuesta en la interpretación de los datos en un sistema de tipificación, describiendo la representación, la interpretación y la estructura de los valores u objetos almacenados en la memoria del ordenador.
2.1 El tipo de datos
El sistema de tipificación usa información de los tipos de datos para comprobar la verificación de los programas que acceden o manipulan los datos.
2.2 Funciones Los programas escritos en un lenguaje funcional están constituidos únicamente por definiciones de funciones, entendiendo éstas no como subprogramas clásicos de un lenguaje imperativo, sino como funciones puramente matemáticas, en las que se verifican ciertas propiedades como la transparencia referencial (el significado de una expresión depende únicamente del significado de sus sobrexpresiones), y por tanto, la carencia total de efectos colaterales.
2.2 Funciones
Existen dos grandes categorías de lenguajes funcionales: los funcionales puros y los híbridos. La diferencia entre ambos estriba en que los lenguajes funcionales híbridos son menos dogmáticos que los puros, al admitir conceptos tomados de los lenguajes imperativos, como las secuencias de instrucciones o la asignación de variables.
2.2 Funciones
En contraste, los lenguajes funcionales puros tienen una mayor potencia expresiva, conservando a la vez su transparencia referencial, algo que no se cumple siempre con un lenguaje funcional híbrido.
2.2 Funciones
Funciones de primera clase y de orden superior Son funciones que pueden tomar otras funciones como argumentos o devolverlos como resultados. En cálculo, un ejemplo de una función de orden superior es el operador diferencial d / dx, que devuelve la derivada de una función f.
2.2 Funciones
Las funciones de orden superior están estrechamente relacionadas con las funciones de primera clase en las cuales las funciones de orden superior y las funciones de primera clase pueden recibir como argumentos y resultados otras funciones.
2.2 Funciones
La distinción entre los dos es sutil: "de orden superior", describe un concepto matemático de funciones que operan sobre otras funciones, mientras que la "primera clase" es un término informático que describe las entidades del lenguaje de programación que no tienen ninguna restricción de su utilización.
2.2 Funciones
Por lo tanto funciones de primera clase pueden aparecer en cualquier parte del programa que otras entidades de primer nivel como los números pueden, incluidos como argumentos a otras funciones y como sus valores de retorno.
2.2 Funciones
Las funciones de orden superior permiten la aplicación parcial, una técnica en la que se aplica una función a sus argumentos uno a la vez, con cada aplicación devuelven una nueva función que acepta el siguiente argumento. Esto le permite a uno expresar, por ejemplo, la función sucesor como el operador de suma aplicada parcialmente al número natural uno.
2.2 Funciones
Funciones puras Las funciones puramente funcionales (o expresiones) no tienen efectos secundarios (memoria o E/S). Esto significa que las funciones puras tienen varias propiedades útiles, muchas de las cuales pueden ser utilizados para optimizar el código:
2.2 Funciones
• Si una función pura se llama con parámetros que no causan efectos secundarios, el resultado es constante con respecto a la lista de parámetros (a veces llamada transparencia referencial), es decir, si la función pura se llama de nuevo con los mismos parámetros, el mismo resultado será devuelto (esto puede habilitar las optimizaciones de almacenamiento en caché).
2.2 Funciones
• Si no se utiliza el resultado de una expresión pura, se puede eliminar sin afectar a otras expresiones. • Si no hay una dependencia de datos entre dos expresiones puras, entonces su orden puede ser invertido, o pueden llevarse a cabo en paralelo y que no pueda interferir con los otros.
2.2 Funciones
• Si el lenguaje no permite efectos secundarios, entonces cualquier estrategia de evaluación se puede utilizar, lo que da la libertad al compilador para reordenar o combinar la evaluación de expresiones en un programa.
2.2 Funciones
La mayoría de los compiladores de lenguajes imperativos detectan funciones puras automáticamente y realizan la eliminación de subexpresiones comunes. Sin embargo no siempre es posible detectarlo en bibliotecas pre-compiladas, porque por norma general no dan esta información.
2.2 Funciones
Esto provoca que no se puedan realizar optimizaciones que podrían aplicar a dichas funciones externas. Algunos compiladores, como gcc, sí que añaden palabras claves adicionales para que el programador marque explícitamente como puras aquellas funciones externas que procedan, de modo que se le apliquen las optimizaciones pertinentes. Fortran 95 también permite que declarar funciones "puras".
2.3 Intervalos
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, el intervalo cubrirá todos los números dentro de su intervalo (incluyendo el máximo y el mínimo).
2.3 Intervalos
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).
2.3 Intervalos
El intervalo de un array son los límites superior e inferior del mismo.
2.3 Intervalos
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.
2.3 Intervalos
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 .
2.4 Operadores
En programación declarativa valores, no hay referencias.
sólo
existen
La distinción entre valores y referencias es fundamental, sin embargo, en la programación imperativa.
2.4 Operadores
Diferencia entre valor y referencia Cuando se realiza una asignación de un valor a una variable debemos considerar que estamos dando un nombre a un objeto matemático que no puede ser modificado o que estamos copiando el valor en la variable.
2.4 Operadores
Por ejemplo, en Java, los tipos de datos primitivos son valores. Las asignaciones valores de estos tipos a variables realizan copias de valores:
2.4 Operadores
En la variable a se copia el valor 4 y en las variables b y c se copia el valor 2. No hay forma de modificar (mutar) esos valores. Podríamos cambiar las variables guardando en ella otros valores, pero los valores propiamente dichos son inmutables. En la última instrucción modificamos el valor de la variable b, pero el valor de la variable c sigue siendo 2.
2.4 Operadores
Los tipos de datos cuyos valores son inmutables y sus asignaciones tienen una semántica de copia reciben el nombre de tipos de valor (value types en inglés). Los tipos de referencia son tipos de datos mutables en los que la asignación funciona con semántica de referencia.
2.4 Operadores
Por ejemplo, cualquier objeto en Java tiene una semántica de referencia. Cuando asignamos un objeto a una variable, estamos guardando en la variable una referencia al objeto.
2.5 Aplicaciones de las listas
Una lista enlazada es una de las estructuras de datos fundamentales, y puede ser usada para implementar otras estructuras de datos. Consiste en una secuencia de nodos, en los que se guardan campos de datos arbitrarios y una o dos referencias, enlaces o punteros al nodo anterior o posterior.
2.5 Aplicaciones de las listas
El principal beneficio de las listas enlazadas respecto a los vectores convencionales es que el orden de los elementos enlazados puede ser diferente al orden de almacenamiento en la memoria o el disco, permitiendo que el orden de recorrido de la lista sea diferente al de almacenamiento.
2.5 Aplicaciones de las listas
Las listas enlazadas permiten inserciones y eliminación de nodos en cualquier punto de la lista en tiempo constante (suponiendo que dicho punto está previamente identificado o localizado), pero no permiten un acceso aleatorio. Existen diferentes tipos de listas enlazadas: listas enlazadas simples, listas doblemente enlazadas, listas enlazadas circulares y listas enlazadas doblemente circulares.
2.5 Aplicaciones de las listas
Algunas funciones: • Caracteres (tipo Char)
• Cadenas (tipo String) • Tipos numéricos: Int, Float
2.5 Aplicaciones de las listas
Componentes: • Los parámetros, que son los valores que recibe la función como entrada; • El código de la función, que son las operaciones que hace la función; El resultado (o valor de retorno), que es el valor final que entrega la función.
2.6 Árboles
En informática un árbol es una estructura de datos ampliamente usada que imita la forma de un árbol (un conjunto de nodos conectados). Un nodo es la unidad sobre la que se construye el árbol y puede tener cero o más nodos hijos conectados a él.
2.6 Árboles
Se dice que un nodo es padre de un nodo si existe un enlace desde hasta (en ese caso, también decimos que es hijo de ). Sólo puede haber un único nodo sin padres, que llamaremos raíz. Un nodo que no tiene hijos se conoce como hoja. Los demás nodos (tienen padre y uno o varios hijos) se les conoce como rama.
2.6 Árboles
2.6 Árboles
Usos comunes de los árboles son: • Representación de datos jerárquicos.
• Como ayuda para realizar búsquedas en conjuntos de datos (ver también: algoritmos de búsqueda en Árboles).
2.7 Evaluación perezosa
En la teoría de lenguajes de programación, La evaluación perezosa (del inglés lazy evaluation) o llamada por necesidad es una estrategia de evaluación que retrasa el cálculo de una expresión hasta que su valor sea necesario, y que también evita repetir la evaluación en caso de ser necesaria en posteriores ocasiones.
2.7 Evaluación perezosa
Esta compartición del cálculo puede reducir el tiempo de ejecución de ciertas funciones de forma exponencial, comparado con otros tipos de evaluación.
2.7 Evaluación perezosa Los beneficios de la evaluación perezosa son:
•
El incremento en el rendimiento al evitar cálculos innecesarios, y en tratar condiciones de error al evaluar expresiones compuestas.
•
La capacidad de construir estructuras de datos potencialmente infinitas.
•
La capacidad de definir estructuras de control como
abstracciones, en lugar de operaciones primitivas.
2.7 Evaluación perezosa
La evaluación perezosa puede también reducir el consumo de memoria de una aplicación, ya que los valores se crean solo cuando se necesitan. Sin embargo, es difícil de combinar con las operaciones típicas de programación imperativa, como el manejo de excepciones o las operaciones de entrada/salida, porque el orden de las operaciones puede quedar indeterminado.
2.7 Evaluación perezosa
Además, la evaluación perezosa puede conducir a fragmentar la memoria. Lo contrario de la evaluación perezosa sería la evaluación acaparadora, o evaluación estricta, que es el modo de evaluación por defecto en la mayoría de los lenguajes de programación.