Miranda (lenguaje de programación)
Miranda (lenguaje de programación) | ||
---|---|---|
? | ||
Información general | ||
Apareció en | 1985 | |
Diseñado por | David Turner | |
Influido por | ML | |
Licencia | 2-clause BSD License | |
Miranda fue desarrollado entre los años 1985 y 1986 por David Turner. Se trata de un lenguaje de programación funcional sucesor de SASL y KRC.
El principal objetivo de este lenguaje era el desarrollar una versión comercial de un lenguaje funcional:
- no-estricto.
- puramente funcional.
Fue comercializado por Research Software Ltd. de Inglaterra, la cual registró la palabra 'Miranda' como marca comercial. Fue el primer lenguaje puramente funcional en ser destinado al uso comercial y no al académico.
La solución a muchos ejemplos de programas resulta más simple en Miranda que en la mayoría de los lenguajes de programación excepto quizás APL, y como otros lenguajes funcionales, sus usuarios comentan que este les permite producir programas fiables en un menor período en comparación con otros lenguajes de programación usados anteriormente.
Salió por primera vez en 1985 como un intérprete rápido en C para los sistemas operativos Unix, con sucesivas entregas en 1987 y 1989. El último lenguaje de programación Haskell es similar un muchos aspectos a Miranda.
Todos los lenguajes de la familia de MIRANDA se caracterizan porque los argumentos se pasan a las funciones sin evaluar (lazy evaluation): el argumento de una función se evalúa cuando la función necesita su valor.
Un programa en este tipo de lenguajes (llamado script) consiste en un conjunto de declaraciones de ecuaciones recursivas y datos de tipo algebraico. La palabra set es importante aquí: el orden de las ecuaciones es, en general, irrelevante, y no es necesario definir una entidad inicial para su uso.
Es raro la necesidad del uso de corchetes y no es necesario el uso de terminaciones de instrucción (;, endif,…)
Los comentarios se inician utilizando los caracteres ‘||’ y continua hasta el final de la línea. Una convención alternativa de comentarios es la que afecta a todo el fichero fuente, conocida como “programación literaria”, en la cual todo línea es comentario a no ser que empiece por el signo’ >’
Los tipos básicos de datos de Miranda son char, num y bool. Una cadena de caracteres no es más que una lista de chars, mientras que num puede representar tanto a enteros como a reales sin necesidad de conversiones explícitas.
Las tuplas son secuencias de elementos de distintos tipos, análogo a los registros de los lenguajes parecidos a Pascal, y son escritos entre paréntesis
this_employee = ("García, Paco", 10560, False, 35)
La lista enlazada en cambio, es la estructura de datos más usada en Miranda. Se escribe entre corchetes y separa cada elemento por comas, los cuales deben de ser del mismo tipo.
week_days = ["Mon","Tue","Wed","Thur","Fri"]
La concatenación de listas es mediante ‘++’, la diferencia con ‘--‘, la construcción con ‘:’ comprobar el tamaño con ‘#’ y devolver el elemento de cierta posición de la lista (indexación) mediante ‘!’
days = week_days ++ ["Sat","Sun"] days = "Nil":days days!0 → "Nil" days = days -- ["Nil"] #days → 7
Existen muchos atajos para construir listas: ‘..’ es usado para listas cuyos elementos forman un serie aritmética, con la posibilidad de especificar un orden de incremento a parte de en 1:
fac n = product [1..n] odd_sum = sum [1,3..100]
Constructores de listas más generales y potentes son aportados por “list comprehensions” (anteriormente conocido como “expresiones ZF”), el cual viene de dos formas: una expresión aplicada una serie de términos:
squares = [ n * n | n <- [1..] ]
(la cual se lee como: lista de cuadrados de n donde n is tomado de la lista de todos los enteros positives) ) y series donde cada término es una función del anterior:
powers_of_2 = [ n | n <- 1, 2*n .. ]
Como estos dos ejemplos muestran, Miranda permite listas con un número infinito de elementos, de los cuales el más simple es la lista de todos los enteros positivos: [1..]
La notación para funciones es simplemente anteponer el nombre de esta a sus parámetros, como en sin x.
En Miranda, como en muchos otros lenguajes puramente funcionales, las funciones son ciudadanos de primera clase, lo que quiere decir que pueden ser pasadas como parámetros de otras funciones, devueltas como resultado o incluidas como elementos de estructuras de datos. Y es más, una función que requiere dos o más parámetros puede ser “parcialmente parametrizada”, no teniendo que usar todos los parámetros. Esto da como resultado otra función que, dando los parámetros que permanecen, devolverá un resultado. Por ejemplo:
add a b = a + b increment = add 1
Es una forma aproximada de crear una función “incremento” la cual suma 1 a sus argumentos. En realidad, add 4 7 toma la función de dos parámetros add , la aplica a 4 obteniendo un función de un solo parámetro que suma 4 a su argumento, y entonces la aplica a 7.
Cualquier función que tome dos parámetros puede transformarse en un operador infijo (por ejemplo, dado la definición de la función anterior add, el término $add es del todo equivalente al operador +) y cada operador infijo que tome dos parámetros puede expresarse como su función correspondiente. Así:
increment = (+) 1
es la forma más simple de crear la función que suma 1 a su argumento. Similarmente, en
half = (/ 2) reciprocal = (1 /)
genera una función de dos parámetros simples. El intérprete entiende en cada caso cual de los dos operadores de la división son aportados, teniendo funciones que respectivamente dividen por 2 y devuelven el inverso.
A pesar de que Miranda es un lenguaje de programación fuertemente tipado, este no insiste en la declaración explícita de tipos. Si el tipo de un función no se declara explícitamente, el intérprete lo deduce de los tipos de sus parámetros y como son usados dentro de la función. Además de los tipos básicos (char, num, bool), se incluye el tipo “nada” donde el tipo del parámetro no importa, como en la función lista inversa:
rev [] = [] rev (a:x) = rev x ++ [a]
que puede ser aplicada a una lista de cualquier tipo de datos, para la que la declaración explícita del tipo seria:
rev :: [*] -> [*]
Finalmente, tiene un mecanismo para crear y manejar módulos de programa cuyas funciones internas son transparentes para las llamadas que otros programas hacen a estos módulos.