Miranda (lenguaje de programación)

Compartir Imprimir Citar

Miranda es un lenguaje de programación perezoso y puramente funcional diseñado por David Turner como sucesor de sus lenguajes de programación anteriores SASL y KRC, utilizando algunos conceptos de ML y Hope. Fue producido por Research Software Ltd. de Inglaterra (que posee una marca comercial con el nombre Miranda) y fue el primer lenguaje puramente funcional que recibió soporte comercial.

Miranda se lanzó por primera vez en 1985 como un intérprete rápido en C para sistemas operativos tipo Unix, con lanzamientos posteriores en 1987 y 1989. Tuvo una fuerte influencia en el posterior lenguaje de programación Haskell.

En 2020 se lanzó una versión de Miranda como código abierto bajo una licencia BSD. La base de código se actualizó para cumplir con los estándares C modernos (C11/C18) y generar archivos binarios de 64 bits. Esto ha sido probado en sistemas operativos que incluyen Debian, Ubuntu, WSL/Ubuntu y MacOS (Catalina).

Resumen

Miranda es un lenguaje de programación perezoso y puramente funcional. Es decir, carece de efectos secundarios y funciones de programación imperativas. Un programa Miranda (llamado script) es un conjunto de ecuaciones que definen varias funciones matemáticas y tipos de datos algebraicos. La palabra conjunto es importante aquí: el orden de las ecuaciones es, en general, irrelevante y no hay necesidad de definir una entidad antes de su uso.

Dado que el algoritmo de análisis hace un uso inteligente del diseño (sangría), rara vez se necesitan declaraciones entre paréntesis y no se requieren terminadores de declaraciones. Esta característica, inspirada en ISWIM, también se usa en occam y Haskell y luego fue popularizada por Python.

Los caracteres || introducen comentarios en los guiones normales y continúan hasta el final de la misma línea. Una convención de comentarios alternativa afecta a un archivo de código fuente completo, conocido como "guión alfabetizado", en el que cada línea se considera un comentario a menos que comience con un signo >.

Los tipos de datos básicos de Miranda son char, num y bool. Una cadena de caracteres es simplemente una lista de char, mientras que num se convierte silenciosamente entre dos formas subyacentes: números enteros de precisión arbitraria (también conocidos como bignums) de forma predeterminada y valores regulares de punto flotante según sea necesario.

Las tuplas son secuencias de elementos de tipos potencialmente mixtos, análogos a los registros en lenguajes similares a Pascal, y se escriben delimitados con paréntesis:

 Esto... = ()"Folland, Mary", 10560, Falso, 35)

La lista en cambio es la estructura de datos más utilizada en Miranda. Se escribe delimitado por corchetes y con elementos separados por comas, debiendo ser todos del mismo tipo:

 semana_días = ["Mon","Tue","Wed","Thur","Fri"]

La concatenación de listas es ++, la resta es --, la construcción es :, el tamaño es # y la indexación es !, entonces:

 días = semana_días ++ ["Sat","Sun"] días = "Nil":días días!0  "Nil" días = días -- ["Nil"] #días  7

Existen varios atajos para la construcción de listas: .. se utiliza para listas cuyos elementos forman una serie aritmética, con la posibilidad de especificar un incremento distinto de 1:

 fac n = producto [1..n] odd_sum = suma [1,3..100]

Las "comprensiones de listas" (anteriormente conocidas como "expresiones ZF"), que vienen en dos formas principales: una expresión aplicada a una serie de términos, por ejemplo:

 cuadrados = [ n * n Silencio n . [1..] ]

(que se lee: lista de n al cuadrado donde n se toma de la lista de todos los enteros positivos) y una serie donde cada término es función del anterior, por ejemplo:

 power_of_2 = [ n Silencio n . 1, 2*n .. ]

Como implican estos dos ejemplos, 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 la aplicación de funciones es simplemente yuxtaposición, como en sin x.

En Miranda, como en la mayoría de los demás lenguajes puramente funcionales, las funciones son ciudadanos de primera clase, lo que quiere decir que pueden pasarse como argumentos a otras funciones, devolverse como resultados o incluirse como elementos de estructuras de datos. Es más, una función con dos o más parámetros puede ser "parcialmente parametrizada", o modificada, proporcionando menos argumentos que el número total de parámetros. Esto da otra función que, dados los parámetros restantes, devolverá un resultado. Por ejemplo:

 añadir a b = a + b aumento = añadir 1

es una forma indirecta de crear una función "incremento" lo que añade uno a su argumento. En realidad, add 4 7 toma la función de dos parámetros add, la aplica a 4 obteniendo una función de un solo parámetro que suma cuatro a su argumento, luego lo aplica a 7.

Cualquier función con dos parámetros (operandos) se puede convertir en un operador infijo (por ejemplo, dada la definición de la función add anterior, el término $add es en todos los sentidos equivalente al operador +) y cada operador infijo que toma dos parámetros se puede convertir en una función correspondiente. De este modo:

 aumento = ()+) 1

es la forma más breve de crear una función que agrega uno a su argumento. Del mismo modo, en

 mitad = ()/ 2) recíproco = ()1 /)

Se generan dos funciones de un solo parámetro. El intérprete entiende en cada caso cuál de los dos parámetros del operador de división se está proporcionando, dando funciones que respectivamente dividen un número por dos y devuelven su recíproco.

Aunque Miranda es un lenguaje de programación fuertemente tipado, no insiste en declaraciones de tipos explícitas. Si el tipo de una función no se declara explícitamente, el intérprete lo infiere del tipo de sus parámetros y cómo se usan dentro de la función. Además de los tipos básicos (char, num, bool), incluye un "cualquier cosa" type donde el tipo de un parámetro no importa, como en la función de inversión de lista:

 rev [] = [] rev ()a:x) = rev x ++ [a]

que se puede aplicar a una lista de cualquier tipo de datos, para los cuales la declaración de tipo de función explícita sería:

 rev :: [*] - [*]

Finalmente, tiene mecanismos para crear y administrar módulos de programa cuyas funciones internas son invisibles para los programas que llaman a esos módulos.

Código de muestra

La siguiente secuencia de comandos de Miranda determina el conjunto de todos los subconjuntos de un conjunto de números

 subsets [] = [[]] subsets ()x:xs) = [[2]x] ++ Sí. Silencio Sí. . Ys] ++ Ys Donde Ys = subsets xs

y este es un script alfabetizado para una función primos que da la lista de todos los números primos

La lista infinita de todos los números primos.

La lista de números primos potenciales comienza como todos los números enteros de 2 en adelante;
como cada primo es devuelto, todos los siguientes números que pueden ser exactamente
dividida por ella se filtran fuera de la lista de candidatos.

[2..]
Sieve (p:x) = p: sieve [n TEN n ANTE n) 0]

Aquí tenemos algunos ejemplos más

max2 :: num - num - nummax2 a b = a, si ab = b, de otra maneramax3 :: num - num - num - nummax3 a b c = max2 ()max2 a b) ()max2 a c)multiplica multiplica multiplica multiplica multiplica multiplica :: num - num - nummultiplica multiplica multiplica multiplica multiplica multiplica 0 b = 0multiplica multiplica multiplica multiplica multiplica multiplica a b = b + ()multiplica multiplica multiplica multiplica multiplica multiplica ()a-1) b)fak :: num - numfak 0 = 1fak n = n * ()fak n-1)numeral::[*]-numnumeral [] = 0numeral ()a:x) = 1 + numeral xsemana::= MoSilencioTuSilencioNosotrosSilencioThSilencioFr.SilencioSaSilencioSuisWorkDay :: semana - boolisWorkDay Sa = FalsoisWorkDay Su = FalsoisWorkDay cualquier día = Cierto.árbol * ::= ESilencio N ()árbol *) * ()árbol *)nodecount :: árbol * - numnodecount E = 0nodecount ()N l w r) = nodecount l + 1 + nodecount rcuenta vacía :: árbol * - numcuenta vacía E = 1cuenta vacía ()N l w r) = cuenta vacía l + cuenta vacía rárbolExample = N () N ()N E 1 E) 3 ()N E 4 E) 5 ()N ()N E 6 E) 8 ()N E 9 E)el día de semanaTree = N () N ()N E Mo E) Tu ()N E Nosotros E) Th ()N ()N E Fr. E) Sa ()N E Su)insertar :: * - Stree * - Stree *insertar x E = N E x Einsertar x ()N l w E) = N l w xinsertar x ()N E w r) = N x w rinsertar x ()N l w r) = insertar x l , si x .w = insertar x r , de otra maneralist2searchtree :: [*] - árbol *list2searchtree [] = Elist2searchtree [x] = N E x Elist2searchtree ()x:xs) = insertar x ()list2searchtree xs)maxel :: árbol * - *maxel E = error "vacío"maxel ()N l w E) = wmaxel ()N l w r) = maxel rminero :: árbol * - *minero E = error "vacío"minero ()N E w r) = wminero ()N l w r) = minero lSilencioTraversing: Voy a través de valores de árbol, poniendo ellos dentro listapreordenado,inorden,postorden :: árbol * - [*]inorden E = []inorden N l w r = inorden l ++ [w] ++ inorden rpreordenado E = []preordenado N l w r = [w] ++ preordenado l ++ preordenado rpostorden E = []postorden N l w r = postorden l ++ postorden r ++ [w]altura :: árbol * - numaltura E = 0altura ()N l w r) = 1 + max2 ()altura l) ()altura r)Monto :: num - numMonto x = x ,si x >= 0Monto x = x*()-1), de otra maneray :: bool - bool - booly Cierto. Cierto. = Cierto.y x Sí. = FalsoSilencio A AVL-Árbol es a árbol Donde el diferencia entre el niño nodos es no superior que 1Silencio i todavía han tenido a prueba estoisAvl :: árbol * - boolisAvl E = Cierto.isAvl ()N l w r) = y ()isAvl l) ()isAvl r), si Monto ()nodecount l) - ()nodecount r) . 2 = Falso, de otra manera   Borrador :: * - árbol * - árbol *Borrador x E = EBorrador x ()N E x E) = EBorrador x ()N E x r) = N E ()minero r) ()Borrador ()minero r) r)Borrador x ()N l x r) = N ()Borrador ()maxel l) l) ()maxel l) rBorrador x ()N l w r) = N ()Borrador x l) w ()Borrador x r)