Icon es un lenguaje de programación de muy alto nivel basado en el concepto de "ejecución orientada a objetivos", donde una expresión en el código devuelve "éxito" junto con un resultado, o "fallo", que indica que no hay un resultado válido. El éxito o el fallo de una expresión se utiliza para dirigir el procesamiento posterior, mientras que los lenguajes convencionales suelen usar lógica booleana escrita por el programador para lograr los mismos fines. Dado que la lógica para las estructuras de control básicas suele ser implícita en Icon, las tareas comunes se pueden completar con menos código explícito.
Icon fue diseñado por Ralph Griswold tras dejar Bell Labs , donde contribuyó significativamente al lenguaje SNOBOL . SNOBOL era un lenguaje de procesamiento de cadenas con una sintaxis que, según los estándares de principios de la década de 1970, se consideraría anticuada. Tras incorporarse a la Universidad de Arizona , desarrolló aún más los conceptos subyacentes de SNOBOL en SL5, pero consideró que el resultado fue un fracaso. Esto dio lugar a Icon, una versión significativamente actualizada que combina el código conciso pero conceptualmente denso de los lenguajes tipo SNOBOL con la sintaxis más familiar de lenguajes inspirados en ALGOL, como C o Pascal .
Al igual que los lenguajes que lo inspiraron, el principal uso de Icon reside en la gestión de cadenas y patrones textuales. Las operaciones con cadenas suelen fallar, por ejemplo, al buscar "the" en "world". En la mayoría de los lenguajes, esto requiere pruebas y bifurcaciones para evitar usar un resultado no válido. En Icon, la mayoría de estas pruebas son innecesarias, lo que reduce la cantidad de código a escribir. El manejo de patrones complejos se puede realizar con pocas líneas de código conciso, similar a lenguajes más especializados como Perl , pero conservando una sintaxis más orientada a funciones, familiar para los usuarios de otros lenguajes tipo ALGOL.
Icon no es orientado a objetos , pero en 1996 se desarrolló una extensión orientada a objetos llamada Idol, que con el tiempo se convirtió en Unicon . También inspiró a otros lenguajes, siendo sus sencillos generadores especialmente influyentes; los generadores de Icon fueron una importante fuente de inspiración para el lenguaje Python . [ 3 ]
Historia
SNOBOL
El proyecto original SNOBOL , conocido retroactivamente como SNOBOL1, se lanzó en otoño de 1962 en el Departamento de Estudios de Investigación de Programación de Bell Labs . [ 4 ] Este proyecto surgió como respuesta a las dificultades para utilizar el lenguaje SCL en la manipulación de fórmulas polinómicas, la integración simbólica y el estudio de cadenas de Markov . SCL, escrito por el jefe del departamento, Chester Lee, era lento y tenía una sintaxis de bajo nivel que generaba grandes volúmenes de código incluso para proyectos sencillos. Tras considerar brevemente el lenguaje COMIT, Ivan Polonsky, Ralph Griswold y David Farber, todos miembros del departamento de seis personas, decidieron escribir su propio lenguaje para resolver estos problemas. [ 5 ]
Las primeras versiones se ejecutaban en el IBM 7090 a principios de 1963, y para el verano ya se habían desarrollado y se utilizaban en toda la empresa Bell. Esto condujo casi de inmediato a SNOBOL2, que añadió varias funciones integradas y la capacidad de enlazar con código ensamblador externo . Se lanzó en abril de 1964 y se utilizó principalmente dentro de Bell, aunque también tuvo cierto uso en el Proyecto MAC . La introducción de las funciones del sistema sirvió principalmente para indicar la necesidad de funciones definidas por el usuario, que fue la característica principal de SNOBOL3, lanzado en julio de 1964. [ 6 ]
La introducción de SNOBOL3 coincidió con cambios importantes en el departamento de computación de Bell Labs, incluyendo la incorporación del nuevo mainframe GE 645, que requeriría una reescritura de SNOBOL. En su lugar, el equipo sugirió escribir una nueva versión que se ejecutaría en una máquina virtual , llamada SIL (por SNOBOL Intermediate Language), lo que permitiría portarla fácilmente a cualquier plataforma suficientemente potente. Esta propuesta fue aceptada como SNOBOL4 en septiembre de 1965. Para entonces, en agosto de 1966, surgieron planes para una versión significativamente mejorada del lenguaje. [ 7 ] El trabajo en el lenguaje continuó durante el resto de la década de 1960, en particular añadiendo el tipo de matriz asociativa en una versión posterior, a la que se referían como una tabla.
SL5 conduce a Icon
Griswold dejó Bell Labs para convertirse en profesor de la Universidad de Arizona en agosto de 1971. [ 8 ] En ese momento introdujo SNOBOL4 como herramienta de investigación. [ 9 ] Recibió subvenciones de la Fundación Nacional de Ciencias para continuar apoyando y desarrollando SNOBOL. [ 10 ]
Como lenguaje desarrollado originalmente a principios de la década de 1960, la sintaxis de SNOBOL presenta características propias de otros lenguajes de programación primitivos como FORTRAN y COBOL . En particular, el lenguaje depende de columnas, ya que muchos de estos lenguajes se introducían en tarjetas perforadas , donde la disposición en columnas resulta natural. Además, las estructuras de control se basaban casi por completo en ramificaciones del código en lugar del uso de bloques , que se estaban convirtiendo en una característica indispensable tras la introducción de ALGOL 60. Para cuando se mudó a Arizona, la sintaxis de SNOBOL4 estaba completamente obsoleta. [ 11 ]
Griswold comenzó el esfuerzo de implementar el concepto subyacente de éxito/fracaso de SNOBOL con estructuras de control de flujo tradicionales como if/then. Esto se convirtió en SL5, abreviatura de "SNOBOL Language 5", pero el resultado fue insatisfactorio. [ 11 ] En 1977, volvió al lenguaje para considerar una nueva versión. Abandonó el sistema de funciones muy potente introducido en SL5 con un concepto más simple de suspender/reanudar y desarrolló un nuevo concepto para el sucesor natural de SNOBOL4 con los siguientes principios; [ 11 ]
- Fundamento filosófico y semántico de SNOBOL4
- Base sintáctica SL5
- Características SL5, excluyendo el mecanismo de procedimiento generalizado.
El nuevo lenguaje se conocía inicialmente como SNOBOL5, pero como era significativamente diferente de SNOBOL en todo excepto en el concepto subyacente, finalmente se buscó un nuevo nombre. Después de considerar "s" como una especie de homenaje a "C", esta idea se descartó debido a los problemas con la composición tipográfica de documentos que usaban ese nombre. Se propusieron y descartaron varios nombres nuevos: Irving, bard y "TL" para "The Language". Fue en este momento cuando Xerox PARC comenzó a publicar sobre su trabajo en interfaces gráficas de usuario y el término "icono" comenzó a entrar en el léxico informático. Se tomó la decisión de cambiar el nombre inicialmente a "icon" antes de finalmente elegir "Icon". [ 11 ] [ a ]
Idioma
Sintaxis básica
El lenguaje Icon se deriva de la clase ALGOL de lenguajes de programación estructurados y, por lo tanto, tiene una sintaxis similar a la de C o Pascal . Icon es muy similar a Pascal, utilizando :=sintaxis para asignaciones, la procedurepalabra clave y sintaxis similar. Por otro lado, Icon utiliza llaves al estilo de C para estructurar grupos de ejecución, y los programas comienzan ejecutando un procedimiento llamado main. [ 13 ]
En muchos sentidos, Icon también comparte características con la mayoría de los lenguajes de scripting (así como con SNOBOL y SL5, de los que se tomaron): las variables no necesitan ser declaradas, los tipos se convierten automáticamente y los números se pueden convertir a cadenas y viceversa automáticamente. [ 14 ] Otra característica común a muchos lenguajes de scripting, pero no a todos, es la falta de un carácter de fin de línea; en Icon, las líneas que no terminan con un punto y coma terminan con un punto y coma implícito si tiene sentido. [ 15 ]
Los procedimientos son los componentes básicos de los programas Icon. Aunque utilizan la nomenclatura de Pascal, funcionan más como funciones de C y pueden devolver valores; functionen Icon no existe la palabra clave `procedimiento`. [ 16 ]
Ejecución orientada a objetivos
Uno de los conceptos clave en SNOBOL era que sus funciones devolvían el "éxito" o el "fracaso" como primitivas del lenguaje en lugar de utilizar números mágicos u otras técnicas. [ 17 ] [ 18 ]
Por ejemplo, una función que devuelve la posición de una subcadena dentro de otra cadena es una rutina común en la mayoría de los sistemas de ejecución de lenguajes . En JavaScript, para encontrar la posición de la palabra "World" dentro de un programa "Hello, World!" se usaría , que devolvería 7 en la variable . Si en cambio se solicita la posición de la subcadena, el código "fallará", ya que el término de búsqueda no aparece en la cadena. En JavaScript, como en la mayoría de los lenguajes, esto se indica devolviendo un número mágico, en este caso -1. [ 19 ]position="Hello, World".indexOf("World")positionposition="Hello, World".indexOf("Goodbye")
En SNOBOL, un fallo de este tipo devuelve un valor especial, &fail. La sintaxis de SNOBOL opera directamente sobre el éxito o el fracaso de la operación, saltando a secciones etiquetadas del código sin tener que escribir una prueba separada. Por ejemplo, el siguiente código imprime "¡Hola, mundo!" cinco veces: [ 20 ]
* Programa SNOBOL para imprimir "Hola Mundo" I = 1 BUCLE SALIDA = "¡Hola, mundo!" I = I + 1 LE ( I , 5 ) : S ( BUCLE ) FINLEPara realizar el bucle, se llama al operador menor o igual que, , sobre la variable de índice I, y si Stiene éxito, es decir, I es menor que 5, se bifurca a la etiqueta nombrada LOOPy continúa. [ 20 ]
Icon conservó el concepto de control de flujo basado en el éxito o el fracaso, pero desarrolló aún más el lenguaje. Un cambio fue la sustitución de la GOTOramificación tipo etiqueta con estructuras orientadas a bloques, en consonancia con el estilo de programación estructurada que se extendía por la industria informática a finales de la década de 1960. [ 11 ] El segundo cambio fue permitir que el "fallo" se propagara a lo largo de la cadena de llamadas, de modo que bloques enteros tuvieran éxito o fallaran en su conjunto. Este es un concepto clave del lenguaje Icon. Mientras que en los lenguajes tradicionales habría que incluir código para comprobar el éxito o el fracaso basándose en la lógica booleana y luego ramificar en función del resultado, dichas comprobaciones y ramificaciones son inherentes al código Icon y no es necesario escribirlas explícitamente. [ 21 ]
Por ejemplo, considere este fragmento de código escrito en el lenguaje de programación Java . Llama a la función read()para leer un carácter de un archivo (previamente abierto), asigna el resultado a la variable ay luego writecopia el valor de aa otro archivo. El resultado es copiar un archivo a otro. readEventualmente se quedará sin caracteres para leer del archivo, posiblemente en su primera llamada, lo que dejaría aen un estado indeterminado y podría writeprovocar una excepción de puntero nulo . Para evitar esto, readdevuelve el valor especial EOF(fin de archivo) en esta situación, lo que requiere una prueba explícita para evitarlo write:
mientras (( a = leer ()) != EOF ) { escribir ( a ); }En cambio, en Icon la read()función devuelve una línea de texto o &fail. &failno es simplemente un análogo de EOF, ya que el lenguaje entiende explícitamente que significa "detener el procesamiento" o "ejecutar el caso de fallo" dependiendo del contexto. El código equivalente en Icon es: [ 18 ]
Esto significa: "siempre que la lectura no falle, llama a la escritura; de lo contrario, detente". [ 18 ] No es necesario especificar una prueba contra el número mágico como en el ejemplo de Java, esto es implícito y el código resultante se simplifica. Debido a que el éxito y el fracaso se transmiten a través de la cadena de llamadas, se pueden incrustar llamadas a funciones dentro de otras y se detienen cuando falla la llamada a la función anidada . Por ejemplo, el código anterior se puede reducir a: [ 22 ]
En esta versión, si la readllamada falla, la writellamada falla y se whiledetiene. [ 22 ] Las estructuras de ramificación y bucle de Icon se basan en el éxito o el fracaso del código que contienen, no en una prueba booleana arbitraria proporcionada por el programador. ifejecuta el thenbloque si su "prueba" devuelve un valor, y ejecuta el elsebloque o pasa a la siguiente línea si devuelve &fail. Del mismo modo, whilecontinúa llamando a su bloque hasta que recibe un fallo. Icon se refiere a este concepto como ejecución dirigida por objetivos . [ 23 ]
Es importante contrastar el concepto de éxito y fracaso con el de excepción ; las excepciones son situaciones inusuales, no resultados esperados. Los fallos en Icon son resultados esperados; llegar al final de un archivo es una situación esperada y no una excepción. Icon no tiene manejo de excepciones en el sentido tradicional, aunque el fallo se usa a menudo en situaciones similares a excepciones. Por ejemplo, si el archivo que se está leyendo no existe, readfalla sin que se indique una situación especial. [ 18 ] En el lenguaje tradicional, estas "otras condiciones" no tienen una forma natural de indicarse; se pueden usar números mágicos adicionales, pero lo más común es que el manejo de excepciones se use para "lanzar" un valor. Por ejemplo, para manejar un archivo faltante en el código Java, se podría ver:
try { while (( a = read ()) != EOF ) { write ( a ); } } catch ( Exception e ) { // algo más salió mal, usa este catch para salir del bucle }Este caso requiere dos comparaciones: una para EOF y otra para todos los demás errores. Dado que Java no permite comparar excepciones como elementos lógicos, como en Icon, try/catchse debe usar la sintaxis extensa. Los bloques try también imponen una penalización de rendimiento incluso si no se lanza ninguna excepción, un costo distribuido que Icon normalmente evita.
Icon utiliza este mismo mecanismo orientado a objetivos para realizar pruebas booleanas tradicionales, aunque con sutiles diferencias. Una comparación simple como no significa "si la evaluación de la expresión condicional resulta en o devuelve un valor verdadero", como ocurriría en la mayoría de los lenguajes; en cambio, significa algo más parecido a "si la expresión condicional tiene éxito y no falla". En este caso, el operador tiene éxito si la comparación es verdadera. Llama a su cláusula si la expresión tiene éxito, y a la siguiente línea si falla. El resultado es similar al tradicional if/then que se ve en otros lenguajes, realiza si es menor que . La sutileza reside en que la misma expresión de comparación puede colocarse en cualquier lugar, por ejemplo:ifa<bthenwrite("a is smaller than b")<ifthenelseifthenab
Otra diferencia es que el <operador devuelve su segundo argumento si tiene éxito, lo que en este ejemplo resultará en que bse escriba el valor de si es mayor que a, de lo contrario no se escribe nada. Como esto no es una prueba en sí , sino un operador que devuelve un valor, se pueden encadenar permitiendo cosas como if a < b < c, [ 22 ] un tipo común de comparación que en la mayoría de los lenguajes debe escribirse como una conjunción de dos desigualdades como if (a < b) && (b < c).
Un aspecto clave de la ejecución dirigida por objetivos es que el programa puede tener que retroceder a un estado anterior si un procedimiento falla, una tarea conocida como retroceso . Por ejemplo, considere el código que establece una variable en una ubicación inicial y luego realiza operaciones que pueden cambiar su valor; esto es común en las operaciones de escaneo de cadenas, por ejemplo, que avanzarán un cursor a través de la cadena a medida que la escanea. Si el procedimiento falla, es importante que cualquier lectura posterior de esa variable devuelva el estado original, no el estado en el que se estaba manipulando internamente. Para esta tarea, Icon tiene el operador de asignación reversible<- , , y el intercambio reversible , <->. Por ejemplo, considere algún código que intenta encontrar una cadena de patrón dentro de una cadena más grande:
Este código comienza moviéndose ia 10, la posición inicial de la búsqueda. Sin embargo, si findfalla, el bloque fallará por completo, lo que resulta en que el valor de ise quede en 10 como un efecto secundario indeseado . Reemplazar con indica que debe restablecerse a su valor anterior si el bloque falla. Esto proporciona un análogo de atomicidad en la ejecución.i := 10i <- 10i
Generadores
En Icon, las expresiones pueden devolver un único valor; por ejemplo, 5 > xse evaluará y devolverá x si su valor es menor que 5, de lo contrario, fallará y no devolverá ningún valor. Icon también incluye el concepto de procedimientos que no devuelven inmediatamente éxito o fracaso, sino que devuelven nuevos valores cada vez que se llaman. Estos se conocen como generadores y son una parte fundamental del lenguaje Icon. En la terminología de Icon, la evaluación de una expresión o función produce una secuencia de resultados . Esta secuencia contiene todos los valores posibles que puede generar la expresión o función. Cuando se agota la secuencia de resultados, la expresión o función falla.
Icon permite que cualquier procedimiento devuelva un único valor o varios valores, controlados mediante las palabras clave fail, returny suspend. Un procedimiento que carece de alguna de estas palabras clave devuelve &fail, lo que ocurre siempre que la ejecución llega al final endde un procedimiento. Por ejemplo:
Llamar f(5)devolverá 1, pero llamar f(-1)devolverá &fail. Esto puede llevar a un comportamiento no obvio, por ejemplo, write(f(-1))no mostrará nada porque ffalla y suspende la operación de write. [ 24 ]
Convertir un procedimiento en un generador utiliza la suspendpalabra clave, que significa "devuelve este valor y, cuando se vuelva a llamar, comienza la ejecución en este punto". En este sentido, es algo así como una combinación del staticconcepto en C y return. Por ejemplo: [ 18 ]
crea un generador que devuelve una serie de números que comienzan en iy terminan en j, y luego devuelve &faildespués de eso. [ b ] Detiene suspend ila ejecución y devuelve el valor de isin restablecer ningún estado. Cuando se realiza otra llamada a la misma función, la ejecución se reanuda en ese punto con los valores anteriores. En este caso, eso hace que realice i +:= 1, vuelva al inicio del bloque while y luego devuelva el siguiente valor y se suspenda de nuevo. Esto continúa hasta que i <= jfalla, momento en el que sale del bloque y llama a fail. Esto permite construir iteradores con facilidad. [ 18 ]
Otro tipo de generador es el alternador , que se ve y funciona como el oroperador booleano. Por ejemplo:
Esto parece decir "si y es menor que x o 5 entonces...", pero en realidad es una forma abreviada de un generador que devuelve valores hasta que se sale del final de la lista. Los valores de la lista se "inyectan" en las operaciones, en este caso, <. Así que en este ejemplo, el sistema primero prueba y < x, si x es mayor que y devuelve el valor de x, la prueba pasa y el valor de y se escribe en la thencláusula. Sin embargo, si x no es mayor que y, falla y el alternador continúa, realizando y < 5. Si esa prueba pasa, se escribe y. Si y no es menor que x ni que 5, el alternador se queda sin pruebas y falla, iffalla y writeno se realiza. Por lo tanto, el valor de y aparecerá en la consola si es menor que x o 5, cumpliendo así el propósito de un booleano or. Las funciones no se llamarán a menos que la evaluación de sus parámetros tenga éxito, por lo que este ejemplo se puede acortar a:
Internamente, el alternador no es simplemente un ory también se puede usar para construir listas arbitrarias de valores. Esto se puede usar para iterar sobre valores arbitrarios, como:
Como las listas de enteros se encuentran comúnmente en muchos contextos de programación, Icon también incluye la topalabra clave para construir generadores de enteros ad hoc :
que se puede abreviar:
El icono no tiene un tipo específico, por lo que las listas del alternador pueden contener diferentes tipos de elementos:
Esto escribe 1, "hola" y tal vez 5 dependiendo del valor de x.
Asimismo, el operador de conjunción , &, se utiliza de forma similar a un andoperador booleano: [ 25 ]
Este código llama a una función ItoJy devuelve un valor inicial de 0, que se asigna a x. Luego realiza la operación del lado derecho de la conjunción y, como es igual a 0, imprime el valor. A continuación, vuelve a llamar al generador, que asigna 1 a x, lo que provoca que la operación del lado derecho falle y no se imprima nada. El resultado es una lista de todos los números enteros pares del 0 al 10. [ 25 ]x % 2ItoJ
El concepto de generadores es particularmente útil y potente cuando se utiliza con operaciones de cadenas, y constituye una base fundamental para el diseño general de Icon. Consideremos la indexOfoperación presente en muchos lenguajes; esta función busca una cadena dentro de otra y devuelve el índice de su ubicación, o un número mágico si no la encuentra. Por ejemplo:
s = "Todo el mundo es un escenario. Y todos los hombres y mujeres son meros actores" ; i = indexOf ( "the" , s ); write ( i );Esto escaneará la cadena s, encontrará la primera aparición de "the" y devolverá ese índice, en este caso 4. Sin embargo, la cadena contiene dos instancias de la cadena "the", por lo que para devolver el segundo ejemplo se utiliza una sintaxis alternativa:
j = indexOf ( "the" , s , i + 1 ); write ( j );Esto le indica que escanee comenzando en la ubicación 5, por lo que no coincidirá con la primera instancia que encontramos anteriormente. Sin embargo, puede que no haya una segunda instancia de "the" (tampoco puede que haya una primera), por lo que el valor de retorno indexOfdebe compararse con el número mágico -1, que se utiliza para indicar que no hay coincidencias. Una rutina completa que imprime la ubicación de cada instancia es:
s = "Todo el mundo es un escenario. Y todos los hombres y mujeres son meros actores" ; i = indexOf ( "the" , s ); while i != - 1 { write ( i ); i = indexOf ( "the" , s , i + 1 ); }En Icon, el equivalente findes un generador, por lo que se pueden crear los mismos resultados con una sola línea:
Por supuesto, hay ocasiones en las que se desea encontrar una cadena después de cierto punto en la entrada, por ejemplo, al escanear un archivo de texto que contiene un número de línea en las primeras cuatro columnas, un espacio y luego una línea de texto. La ejecución orientada a objetivos se puede utilizar para omitir los números de línea:
La posición solo se devolverá si "the" aparece después de la posición 5; de lo contrario, la comparación fallará, se pasará el fallo a la escritura y no se producirá la escritura.
El everyoperador es similar a while, que recorre cada elemento devuelto por un generador y sale en caso de fallo: [ 24 ]
Existe una diferencia clave entre everyy while; whilereevalúa el primer resultado hasta que falla, mientras que everyobtiene el siguiente valor de un generador. everyen realidad inyecta valores en la función de una manera similar a los bloques en Smalltalk . Por ejemplo, el bucle anterior se puede reescribir de esta manera: [ 24 ]
En este caso, los valores de i a j se inyectarán someFunctiony (potencialmente) escribirán varias líneas de salida. [ 24 ]
Colecciones
Icon incluye varios tipos de colecciones, incluyendo listas que también pueden usarse como pilas y colas , tablas (también conocidas como mapas o diccionarios en otros lenguajes), conjuntos y otros. Icon se refiere a estos como estructuras . Las colecciones son generadores inherentes y se pueden llamar fácilmente usando la sintaxis de signo de exclamación. Por ejemplo:
Utilizando la propagación de fallos como se vio en ejemplos anteriores, podemos combinar las pruebas y los bucles:
Dado que la colección de listas es un generador, esto se puede simplificar aún más con la sintaxis de signo de exclamación:
En este caso, el signo de exclamación writehace que Icon devuelva una línea de texto una por una desde el array y finalmente falle al final. &inputes un análogo basado en generador de readque lee una línea desde la entrada estándar , por lo que !&inputcontinúa leyendo líneas hasta que termina el archivo.
Como Icon no admite tipos, las listas pueden contener cualquier tipo de valores:
Los elementos pueden incluir otras estructuras. Para crear listas más grandes, Icon incluye el listgenerador; genera una lista que contiene 10 copias de "palabra". Al igual que los arreglos en otros lenguajes, Icon permite buscar elementos por posición, por ejemplo, . Se incluye el seccionamiento de arreglos , lo que permite crear nuevas listas a partir de los elementos de otras listas, por ejemplo, produce una nueva lista llamada aCat que contiene "tabby" y 2002.i := list(10, "word")weight := aCat[4]aCat := Cats[2:4]
Las tablas son esencialmente listas con claves de índice arbitrarias en lugar de números enteros:
Este código crea una tabla que utilizará cero como valor predeterminado para cualquier clave desconocida. A continuación, añade dos elementos a la tabla, con las claves "there" y "here", y los valores 1 y 2.
Los conjuntos también son similares a las listas, pero contienen solo un único miembro de cada valor. Icon incluye la ++unión de dos conjuntos, **la intersección y --la diferencia. Icon incluye varios "Cset" predefinidos, conjuntos que contienen diversos caracteres. Hay cuatro Cset estándar en Icon: &ucase, &lcase, &letters, y &digits. Se pueden crear nuevos Cset encerrando una cadena entre comillas simples, por ejemplo, .vowel := 'aeiou'
Instrumentos de cuerda
En Icon, las cadenas son listas de caracteres. Como lista, son generadores y, por lo tanto, se pueden iterar sobre ellas utilizando la sintaxis de signo de exclamación:
Imprimirá cada carácter de la cadena en una línea separada.
Se pueden extraer subcadenas de una cadena utilizando una especificación de rango entre corchetes. Una especificación de rango puede devolver un punto a un solo carácter o a una porción de la cadena. Las cadenas se pueden indexar tanto desde la derecha como desde la izquierda. Las posiciones dentro de una cadena se definen entre los caracteres 1 A 2 B 3 C 4 y se pueden especificar desde la derecha : −3 A −2 B −1 C 0
Por ejemplo,
Donde el último ejemplo muestra el uso de una longitud en lugar de una posición final.
La especificación de subíndices se puede usar como un lvalue dentro de una expresión. Esto se puede usar para insertar cadenas dentro de otra cadena o eliminar partes de una cadena. Por ejemplo:
escaneo de cadenas
Una simplificación adicional para el manejo de cadenas es el sistema de escaneo? , invocado con , que llama a funciones sobre una cadena:
Icon se refiere al lado izquierdo de la cadena ?como el sujeto y lo pasa a las funciones de cadena. Recordemos que findtoma dos parámetros: el texto de búsqueda como primer parámetro y la cadena a buscar como segundo parámetro. El uso ?del segundo parámetro es implícito y no es necesario que lo especifique el programador. En los casos comunes en que se llaman varias funciones a una sola cadena en secuencia, este estilo puede reducir significativamente la longitud del código resultante y mejorar la claridad. Las firmas de las funciones de Icon identifican el parámetro sujeto en sus definiciones para que el parámetro pueda elevarse de esta manera.
Esto ?no es simplemente una forma de azúcar sintáctico , sino que también establece un "entorno de escaneo de cadenas" para cualquier operación de cadena posterior. Esto se basa en dos variables internas: &subjecty &pos; &subjectes simplemente un puntero a la cadena original, mientras que &poses la posición actual dentro de ella, o cursor. Los diversos procedimientos de manipulación de cadenas de Icon utilizan estas dos variables, por lo que no es necesario que el programador las proporcione explícitamente. Por ejemplo:
produciría:
asunto=[esta es una cadena], posición=[1] Se pueden usar funciones integradas y definidas por el usuario para desplazarse dentro de la cadena que se está analizando. Todas las funciones integradas se configurarán por defecto &subjectpara &pospermitir el uso de la sintaxis de análisis. El siguiente código escribirá todas las "palabras" delimitadas por espacios en blanco en una cadena:
Hay varias funciones nuevas introducidas en este ejemplo. posdevuelve el valor actual de &pos. Puede que no sea inmediatamente obvio por qué se necesitaría esta función y no simplemente usar el valor de &posdirectamente; la razón es que &poses una variable y por lo tanto no puede tomar el valor &fail, que el procedimiento possí puede. Por lo tanto posproporciona un envoltorio ligero en &posque permite que el control de flujo dirigido por objetivos de Icon se use fácilmente sin tener que proporcionar pruebas booleanas escritas a mano contra &pos. En este caso, la prueba es "es &pos cero", que, en la numeración impar de las ubicaciones de cadena de Icon, es el final de la línea. Si no es cero, posdevuelve &fail, que está invertido con el noty el bucle continúa.
manyencuentra uno o más ejemplos del parámetro Cset proporcionado comenzando en el actual &pos. En este caso, está buscando caracteres de espacio, por lo que el resultado de esta función es la ubicación del primer carácter que no sea un espacio después de &pos. tabse mueve &posa esa ubicación, nuevamente con un posible &failen caso de que, por ejemplo, manycaiga fuera del final de la cadena. uptoes esencialmente lo opuesto a many; devuelve la ubicación inmediatamente anterior a su Cset proporcionado, que el ejemplo luego establece a &poscon otro tab. La alternancia se usa para detenerse también al final de una línea.
Este ejemplo se puede hacer más robusto mediante el uso de un Cset de "salto de palabras" más apropiado que podría incluir puntos, comas y otros signos de puntuación, así como otros caracteres de espacio en blanco como tabulaciones y espacios de no separación. Ese Cset se puede usar luego en manyy upto.
Un ejemplo más complejo demuestra la integración de generadores y escaneo de cadenas dentro del lenguaje.
Críticas
Laurence Tratt escribió un artículo sobre Icon examinando sus aplicaciones en el mundo real y señalando varias áreas de preocupación. Entre ellas se encontraban varias decisiones prácticas que derivan de sus orígenes en el procesamiento de cadenas, pero que no tienen tanto sentido en otras áreas. [ 24 ] Entre ellas:
La decisión de fallar por defecto al final de los procedimientos tiene sentido en el contexto de los generadores, pero menos en el caso de los procedimientos generales. Volviendo al ejemplo mencionado anteriormente, write(f(-1))no se obtendrá la salida esperada. Sin embargo: [ 24 ]
Esto dará como resultado que se imprima 10. Este tipo de problema no es nada obvio, ya que incluso en un depurador interactivo se invoca todo el código, pero xnunca se obtiene el valor esperado. Esto podría descartarse como uno de esos "problemas" que los programadores deben tener en cuenta en cualquier lenguaje, pero Tratt examinó varios programas de Icon y descubrió que la gran mayoría de los procedimientos no son generadores. Esto significa que el comportamiento predeterminado de Icon solo lo utiliza una pequeña minoría de sus construcciones, pero representa una fuente importante de posibles errores en todas las demás. [ 24 ]
Otro problema es la falta de un tipo de dato booleano [ c ] y lógica booleana convencional. Si bien el sistema de éxito/fracaso funciona en la mayoría de los casos donde el objetivo final es verificar un valor, esto aún puede generar un comportamiento extraño en código aparentemente simple: [ 25 ]
Este programa imprimirá "tomado". La razón es que la prueba, c, devuelve un valor; ese valor es &null, el valor predeterminado para todas las variables no inicializadas. [ 26 ]&null es un valor válido, por lo que if ctiene éxito. Para probar esto, es necesario hacer la prueba explícita, c === &null(o la expresión Icon más idiomática if /c then ...). Tratt supuso que esto resta valor al código autodocumentado , al haber supuesto erróneamente que está probando "es c cero" o "existe c". [ 25 ]
Véase también
Notas
- ↑ Según una entrevista de 1985, Griswold afirma que el término «icono» no se utilizaba hasta que Smalltalk se lanzó al público tiempo después. Expresó su molestia porque el término estaba confundiendo a la gente que pensaba que el lenguaje tenía elementos gráficos. [ 12 ]
- ↑ El
failno es necesario en este caso ya que está inmediatamente antes delend. Se ha añadido para mayor claridad. - ↑ Aunque, como señala Tratt, K&R C también carece de un tipo booleano explícito y usa 0 para falso y cualquier valor distinto de cero para verdadero. [ 24 ]
Referencias
Citas
- ↑ Townsend, Gregg (7 de septiembre de 2025). "Versión v9.5.25a" . GitHub .
- ↑ "Goaldi" . GitHub .
- ↑ Schemenauer, Neil; Peters, Tim; Hetland, Magnus Lie (18 de mayo de 2001). "PEP 255 – Generadores simples" . Propuestas de mejora de Python . Python Software Foundation . Consultado el 9 de febrero de 2012 .
- ↑ Griswold 1981 , págs. 601, 602.
- ↑ Griswold 1981 , págs. 602.
- ↑ Griswold 1981 , págs. 606.
- ↑ Griswold 1981 , págs. 608.
- ↑ Griswold 1981 , págs. 609.
- ↑ Griswold 1981 , págs. 629.
- ↑ Shapiro 1985 , págs. 346.
- 1 2 3 4 5 Griswold y Griswold 1993 , pág. 53.
- ↑ Shapiro 1985 , pág. 350.
- ↑ Griswold y Griswold 2002 , pág. xv.
- ↑ Griswold y Griswold 2002 , pág. xvi.
- ↑ Griswold y Griswold 2002 , pág. 10.
- ↑ Griswold y Griswold 2002 , pág. 1.
- ↑ Griswold y Griswold 2002 , pág. 4.
- ^ Tratt 2010 , pág . 74.
- ↑ "Array.prototype.indexOf()" . MDN Web Docs . 27 de junio de 2023.
- 1 2 Lane, Rupert (26 de julio de 2015). "SNOBOL - Introducción" . Pruebe MTS .
- ↑ Tratt 2010 , pág. 73.
- 1 2 3 Griswold 1996 , pág. 2.1.
- ↑ Griswold 1996 , pág. 1.
- ^ Tratt 2010 , pág . 75.
- 1 2 3 4 Tratt 2010 , pág. 76.
- ↑ Griswold y Griswold 2002 , pág. 128.
Bibliografía
- Griswold, Ralph; Griswold, Madge (2002). El lenguaje de programación Icon (tercera ed.). Comunicaciones punto a punto. ISBN 1-57398-001-3.
- Griswold, Ralph; Griswold, Madge (marzo de 1993). "Historia del lenguaje de programación Icon" . SIGPLAN Notices . 23 (3): 53– 68. doi : 10.1145/155360.155363 . S2CID 861936 .
- Griswold, Ralph (1981). "Una historia de los lenguajes de programación SNOBOL" . En Wexelblat, Richard (ed.). Historia de los lenguajes de programación . Academic Press. doi : 10.1145/800025.1198417 . S2CID 42902371 .
- Griswold, Ralph (2 de marzo de 1996). "Una descripción general del lenguaje de programación Icon; versión 9" . Departamento de Ciencias de la Computación, Universidad de Arizona .
- Tratt, Laurence (18 de octubre de 2010). «Experiencias con un sistema de evaluación de expresiones tipo icono» (PDF) . Actas del 6.º simposio sobre lenguajes dinámicos . págs. 73-80 . doi : 10.1145/1869631.1869640 . ISBN 9781450304054. S2CID 14588067 .
- Shapiro, Ezra (julio de 1985). "SNOBOL e Icono" . Byte . págs. 341–350 .
Enlaces externos
- Sitio web oficial
- Icono en GitHub
- Entrevista de historia oral con Stephen Wampler , del Instituto Charles Babbage de la Universidad de Minnesota. Wampler habla sobre su trabajo en el desarrollo de Icon a finales de la década de 1970.
- Entrevista de historia oral con Robert Goldberg , del Instituto Charles Babbage de la Universidad de Minnesota. Goldberg habla sobre su interacción con Griswold mientras trabajaban en Icon en el aula del Instituto Tecnológico de Illinois .
- Entrevista de historia oral con Kenneth Walker , del Instituto Charles Babbage de la Universidad de Minnesota. Walker describe el entorno de trabajo del proyecto Icon, sus interacciones con Griswold y su propio trabajo en un compilador de Icon.
- La página del lenguaje de programación Icon en el sitio web del proyecto de tareas de programación comparativa de The Rosetta Code.
- Lenguajes de programación de tipado dinámico
- Familia de lenguajes de programación Icon
- Lenguajes de programación que coinciden con patrones
- Software de dominio público
- Familia de lenguajes de programación SNOBOL
- Lenguajes de programación orientados a texto
- Lenguajes de programación creados en 1977