Articulo de referencia

Miranda (lenguaje de programación)

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 , utilizand...

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 la marca registrada del nombre Miranda ) [ 3 ] y fue el primer lenguaje puramente funcional en contar con 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 Haskell . [ 4 ] Turner afirmó que las ventajas de Miranda sobre Haskell son: "Lenguaje más pequeño, sistema de tipos más simple, aritmética más simple". [ 5 ]

En 2020 se publicó una versión de Miranda como código abierto bajo una licencia BSD . El código se actualizó para cumplir con los estándares modernos de C ( C11 / C18 ) y generar binarios de 64 bits. Esto se probó en sistemas operativos como Debian , Ubuntu , WSL /Ubuntu y macOS ( Catalina ). [ 5 ] [ 6 ]

Nombre

Miranda, de John William Waterhouse, 1917

El nombre Miranda se toma de la forma gerundiva del verbo latino miror , [ 7 ] que significa "ser admirado".

El logotipo presenta una ilustración de John William Waterhouse del personaje de Miranda , de la obra La Tempestad de Shakespeare .

Descripción general

Miranda es un lenguaje de programación perezoso y puramente funcional . Es decir, carece de efectos secundarios y características de programación imperativa . Un programa Miranda (llamado script ) es un conjunto de ecuaciones que definen diversas funciones matemáticas y tipos de datos algebraicos . El término « conjunto» es importante aquí: el orden de las ecuaciones es, en general, irrelevante, y no es necesario definir una entidad antes de su uso.

Dado que el algoritmo de análisis sintáctico utiliza de forma inteligente la disposición (sangría, mediante la regla de desplazamiento ), rara vez se necesitan corchetes y los terminadores de sentencia son innecesarios. Esta característica, inspirada en ISWIM , también se utiliza en occam y Haskell , y posteriormente fue popularizada por Python .

Los comentarios se introducen en los guiones regulares mediante caracteres ||y continúan hasta el final de la misma línea. Una convención de comentarios alternativa afecta a todo un archivo de código fuente, conocido como " guion literario ", 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, numy bool. Una cadena de caracteres es simplemente una lista de char, mientras que numse convierte silenciosamente entre dos formas subyacentes: enteros de precisión arbitraria (también conocidos como bignums) por defecto, y valores de punto flotante regulares según sea necesario.

Las tuplas son grupos de elementos de tipos potencialmente mixtos, en un orden fijo, análogos a los registros en lenguajes tipo Pascal , pero con campos sin nombre. Se delimitan con paréntesis:

este_empleado = ( "Folland, Mary" , 10560 , Falso , 35 )

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

días_de_la_semana = [ "Lun" , "Mar" , "Mié" , "Jue" , ​​"Vie" ]

La concatenación de listas es ++, la resta es --, la construcción es :, el dimensionamiento es #y la indexación es !, por lo tanto:

días = días_semana ++ [ "Sáb" , "Dom" ] días = "Nulo" : días días ! 0 "Nulo" días = días -- [ "Nulo" ] # días 7

Existen varios atajos para la creació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") proporcionan funcionalidades más generales y potentes para la creación de listas , y se presentan en dos formas principales: una expresión aplicada a una serie de términos, por ejemplo:

cuadrados = [ n * n | 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 una función del anterior, por ejemplo:

potencias_de_2 = [ n | n <- 1 , 2 * n .. ]

Como sugieren estos dos ejemplos, Miranda permite listas con un número infinito de elementos, de las cuales la más simple es la lista de todos los números 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 lenguajes puramente funcionales, las funciones son elementos de primera clase ; es decir, pueden pasarse como argumentos a otras funciones, devolverse como resultados o incluirse como elementos de estructuras de datos. Además, una función con dos o más parámetros puede "parcialmente parametrizada" o currificada , proporcionándole menos argumentos que el número total de parámetros. Esto da como resultado otra función que, con los parámetros restantes, devolverá un resultado. Por ejemplo:

sumar a b = a + b incremento = sumar 1

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

Cualquier función con dos parámetros (operandos) puede transformarse en un operador infijo (por ejemplo, dada la definición de la addfunción anterior, el término $addes en todos los sentidos equivalente al +operador) y todo operador infijo que toma dos parámetros puede transformarse en una función correspondiente. Por lo tanto:

incremento = ( + ) 1

es la forma más breve de crear una función que suma uno a su argumento. De manera similar, 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 como resultado funciones que dividen un número entre dos y devuelven su recíproco.

Aunque Miranda es un lenguaje de programación fuertemente tipado , no exige declaraciones de tipo 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 de cómo se utilizan dentro de la función. Además de los tipos básicos ( char, num, bool), incluye un tipo "cualquier cosa" donde el tipo de un parámetro no importa, como en la función de inversión de listas:

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

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

rev :: [ * ] -> [ * ]

Por último, dispone de mecanismos para crear y gestionar módulos de programa cuyas funciones internas son invisibles para los programas que llaman a dichos módulos.

Código de ejemplo

El siguiente script de Miranda define la lista de todas las sublistas de una lista dada.

sublistas [] = [ [] ] sublistas ( x : xs ) = [[ x ] ++ y | y <- ys ] ++ ys donde ys = sublistas xs

y este es un script literario para una función primes que devuelve la lista de todos los números primos.

> || La lista infinita de todos los números primos. La lista de posibles números primos comienza con todos los números enteros a partir del 2; a medida que se devuelve cada número primo, todos los siguientes números que pueden ser exactamente Los candidatos divididos por ese criterio son excluidos de la lista de candidatos. > primos = criba [2..] > tamiz (p:x) = p : tamiz [n | n <- x; n mod p ~= 0] 

Aquí tenemos algunos ejemplos más.

max2 :: num -> num -> num max2 a b = a , si a > b = b , en caso contrariomax3 :: num -> num -> num -> num max3 a b c = max2 ( max2 a b ) ( max2 a c )fak :: núm -> núm fak 0 = 1 fak n = n * fak ( n - 1 )itemnumber :: [ * ] -> num itemnumber [] = 0 itemnumber ( a : x ) = 1 + itemnumber xdía laborable ::= Lun | Tu | Nosotros | Ju | fr | sa | SuisWorkDay :: weekday -> bool isWorkDay Sa = False isWorkDay Do = False isWorkDay anyday = Trueárbol * ::= E | N ( árbol * ) * ( árbol * )nodecount :: tree * -> num nodecount E = 0 nodecount ( N l w r ) = nodecount l + 1 + nodecount remptycount :: árbol * -> num emptycount E = 1 emptycount ( N l w r ) = emptycount l + emptycount rárbolEjemplo = N ( N ( N E 1 E ) 3 ( N E 4 E )) 5 ( N ( N E 6 E ) 8 ( N E 9 E )) día de la semana Árbol = N ( N ( N E Mo E ) Tu ( N E We E )) Th ( N ( N E Fr E ) Sa ( N E Su ))insertar :: * -> calle * -> calle * insertar x E = N E x E insertar x ( N l w E ) = N l w x insertar x ( N E w r ) = N x w r insertar x ( N l w r ) = insertar x l , si x < w = insertar x r , en otro casolist2searchtree :: [ * ] -> árbol * list2searchtree [] = E list2searchtree [ x ] = N E x E list2searchtree ( x : xs ) = insertar x ( list2searchtree xs )maxel :: árbol * -> * maxel E = error "vacío" maxel ( N l w E ) = w maxel ( N l w r ) = maxel rminel :: árbol * -> * minel E = error "vacío" minel ( N E w r ) = w minel ( N l w r ) = minel lRecorrido : recorrer los valores del árbol y colocarlos en una lista .preorden , inorder , postorden :: árbol * -> [ * ] inorder E = [] inorder N l w r = inorder l ++ [ w ] ++ inorder rpreorden E = [] preorden N l w r = [ w ] ++ preorden l ++ preorden rorden posterior E = [] orden posterior N l w r = orden posterior l ++ orden posterior r ++ [ w ]altura :: árbol * -> num altura E = 0 altura ( N l w r ) = 1 + max2 ( altura l ) ( altura r )cantidad :: num -> num cantidad x = x , si x >= 0 cantidad x = x * ( -1 ) , en caso contrarioy :: bool -> bool -> bool y Verdadero Verdadero = Verdadero y x y = Falso|| Un árbol AVL es un árbol donde la diferencia entre los nodos hijos no es mayor que 1 || Todavía tengo que probar estoisAvl :: árbol * -> bool isAvl E = True isAvl ( N l w r ) = and ( isAvl l ) ( isAvl r ), if amount (( nodecount l ) - ( nodecount r )) < 2 = False , otherwiseeliminar :: * -> árbol * -> árbol * eliminar x E = E eliminar x ( N E x E ) = E eliminar x ( N E x r ) = N E ( minel r ) ( eliminar ( minel r ) r ) eliminar x ( N l x r ) = N ( eliminar ( maxel l ) l ) ( maxel l ) r eliminar x ( N l w r ) = N ( eliminar x l ) w ( eliminar x r )

Referencias

  1. "Página de descarga de Miranda" . Consultado el 17 de mayo de 2024 .
  2. "miranda: COPIA" . Consultado el 17 de mayo de 2024 .
  3. Turner, DA (septiembre de 1985). «Miranda: Un lenguaje funcional no estricto con tipos polimórficos» (PDF) . En Jouannaud, Jean-Pierre (ed.). Lenguajes de programación funcional y arquitectura de computadoras . Lecture Notes in Computer Science. Vol. 201. Berlín, Heidelberg: Springer. pp. 1–16 . doi : 10.1007/3-540-15975-4_26 . ISBN   978-3-540-39677-2.
  4. Hudak, Paul; Hughes, John; Peyton Jones, Simon; Wadler, Philip (2007-06-09). "Una historia de Haskell: Ser perezoso con clase" . Actas de la tercera conferencia ACM SIGPLAN sobre la historia de los lenguajes de programación . Nueva York, NY, EE. UU.: ACM. doi : 10.1145/1238844.1238856 . ISBN 9781595937667. S2CID 52847907 . 
  5. 1 2 Turner, David (22 de marzo de 2021). "Open Sourcing Miranda" . Code Sync . Londres (publicado en noviembre de 2020) . Recuperado el 30 de diciembre de 2021 .
  6. "Página de descarga de Miranda" . www.cs.kent.ac.uk. Consultado el 30 de diciembre de 2021 .
  7. "Acerca del nombre Miranda" . Consultado el 18 de mayo de 2024 .
  • Sitio web oficialEdita esto en Wikidata
  • La versión de código abierto que se mantiene actualmente del intérprete de Miranda del profesor Turner.
  • La biblioteca matemática de precisión infinita , un gran ejemplo de programación en Miranda (y Haskell).