Scheme es un dialecto minimalista de la familia Lisp de lenguajes de programación . Scheme consta de un pequeño núcleo estándar con varias herramientas para la extensión del idioma. [1]
Paradigmas | Multi-paradigma : funcional , imperativo , meta |
---|---|
Familia | Ceceo |
Diseñada por | Guy L. Steele y Gerald Jay Sussman |
Apareció por primera vez | 1975 |
Lanzamiento estable | R7RS / 2013 |
Disciplina de mecanografía | Dinámico , latente , fuerte |
Alcance | Léxico |
Extensiones de nombre de archivo | .scm, .ss |
Sitio web | www |
Implementaciones importantes | |
Muchas (ver implementaciones de Scheme ) | |
Influenciado por | |
ALGOL , Lisp , MDL | |
Influenciado | |
Clojure , Common Lisp , Dylan , EuLisp , Haskell , Hop , JavaScript , Julia , Lua , MultiLisp , R , Racket , Ruby , Rust , S , Scala , T | |
|
Scheme fue creado durante la década de 1970 en el MIT AI Lab y lanzado por sus desarrolladores, Guy L. Steele y Gerald Jay Sussman , a través de una serie de memorandos ahora conocidos como Lambda Papers . Fue el primer dialecto de Lisp en elegir el alcance léxico y el primero en requerir implementaciones para realizar la optimización de la llamada final , lo que brinda un soporte más sólido para la programación funcional y las técnicas asociadas, como los algoritmos recursivos. También fue uno de los primeros lenguajes de programación en admitir continuaciones de primera clase . Tuvo una influencia significativa en el esfuerzo que condujo al desarrollo de Common Lisp . [2]
El lenguaje Scheme está estandarizado en el funcionario IEEE estándar [3] y una de facto estándar llamado el Revisada n Informe sobre la Lengua esquema algorítmico (R n RS). El estándar más implementado es R5RS (1998). [4] El estándar más reciente, R7RS, [5] proporciona versiones "pequeñas" y "grandes" del lenguaje Scheme; el estándar de lenguaje "pequeño" fue ratificado en 2013. [6] Scheme tiene una base de usuarios diversa debido a su compacidad y elegancia, pero su filosofía minimalista también ha causado una amplia divergencia entre las implementaciones prácticas, tanto que el Comité Directivo del Esquema lo llama " el lenguaje de programación más intransitable del mundo "y" una familia de dialectos "en lugar de un solo idioma. [7]
Historia
Orígenes
Esquema comenzó en la década de 1970 como un intento de comprender Carl Hewitt 's modelo de actor , para lo cual Steele y Sussman escribieron una 'pequeña intérprete Lisp' usando Maclisp y luego 'mecanismos adicionales para la creación de los actores y el envío de mensajes'. [8] Scheme se llamó originalmente "Schemer", en la tradición de otros lenguajes derivados de Lisp como Planner o Conniver . El nombre actual resultó del uso por parte de los autores del sistema operativo ITS , que limitaba los nombres de archivo a dos componentes de un máximo de seis caracteres cada uno. Actualmente, "Schemer" se usa comúnmente para referirse a un programador de Scheme.
R6RS
Un nuevo proceso de estandarización del lenguaje comenzó en el taller del Esquema de 2003, con el objetivo de producir un estándar R6RS en 2006. Este proceso rompió con el anterior enfoque de unanimidad R n RS.
R6RS [9] presenta un sistema de módulos estándar, lo que permite una división entre el lenguaje principal y las bibliotecas. Se publicaron varios borradores de la especificación R6RS, siendo la versión final R5.97RS. Una votación exitosa resultó en la ratificación de la nueva norma, anunciada el 28 de agosto de 2007. [9]
Actualmente, las versiones más recientes de varias implementaciones de Scheme [10] son compatibles con el estándar R6RS. Existe una implementación de referencia portátil de las bibliotecas en fase implícita propuestas para R6RS, llamada psyntax, que se carga y se inicia correctamente en varias implementaciones de Scheme más antiguas. [11]
Una característica de R6RS es el descriptor de tipo de registro (RTD). Cuando se crea y se utiliza un RTD, la representación del tipo de registro puede mostrar el diseño de la memoria. También calculó la máscara de bits del campo del objeto y las máscaras de bits del campo del objeto Scheme mutable, y ayudó al recolector de basura a saber qué hacer con los campos sin tener que recorrer toda la lista de campos que se guardan en el RTD. RTD permite a los usuarios expandir el RTD básico para crear un nuevo sistema de registro. [12]
R6RS introduce numerosos cambios significativos en el lenguaje. [13] El código fuente ahora está especificado en Unicode , y un gran subconjunto de caracteres Unicode puede aparecer ahora en los símbolos e identificadores de Scheme , y hay otros cambios menores en las reglas léxicas. Los datos de caracteres ahora también se especifican en Unicode. Muchos procedimientos estándar se han trasladado a las nuevas bibliotecas estándar, que a su vez forman una gran expansión del estándar, que contienen procedimientos y formas sintácticas que antes no formaban parte del estándar. Se ha introducido un nuevo sistema de módulos y los sistemas para el manejo de excepciones ahora están estandarizados. Syntax-rules ha sido reemplazada por una facilidad de abstracción sintáctica más expresiva (syntax-case) que permite el uso de todo Scheme en tiempo de macro expansión. Ahora se requieren implementaciones compatibles para admitir la torre numérica completa de Scheme , y la semántica de los números se ha ampliado, principalmente en la dirección del soporte para el estándar IEEE 754 para la representación numérica de punto flotante.
R7RS
El estándar R6RS ha causado controversia porque se ve que se ha apartado de la filosofía minimalista. [14] [15] En agosto de 2009, el Comité Directivo del Esquema, que supervisa el proceso de estandarización, anunció su intención de recomendar la división del Esquema en dos lenguajes: un gran lenguaje de programación moderno para programadores; y una versión pequeña, un subconjunto de la versión grande que conserva el minimalismo elogiado por los educadores y los implementadores casuales. [7] Se crearon dos grupos de trabajo para trabajar en estas dos nuevas versiones del Esquema. El sitio del proceso de informes del esquema tiene enlaces a los estatutos de los grupos de trabajo, las discusiones públicas y el sistema de seguimiento de problemas.
El noveno borrador de la R7RS (lenguaje pequeño) se puso a disposición el 15 de abril de 2013. [16] La votación para ratificar este borrador se cerró el 20 de mayo de 2013, [17] y el informe final está disponible desde el 6 de agosto de 2013, describiendo "El lenguaje 'pequeño' de ese esfuerzo: por lo tanto, no puede considerarse de forma aislada como el sucesor de R6RS". [6]
Características distintivas
Scheme es principalmente un lenguaje de programación funcional . Comparte muchas características con otros miembros de la familia de lenguajes de programación Lisp. La sintaxis muy simple de Scheme se basa en expresiones-s , listas entre paréntesis en las que un operador de prefijo va seguido de sus argumentos. Por tanto, los programas de esquema constan de secuencias de listas anidadas. Las listas también son la estructura de datos principal en Scheme, lo que lleva a una estrecha equivalencia entre el código fuente y los formatos de datos ( homoiconicidad ). Los programas de Scheme pueden crear y evaluar fácilmente fragmentos de código de Scheme de forma dinámica.
La dependencia de las listas como estructuras de datos es compartida por todos los dialectos Lisp. Scheme hereda un rico conjunto de primitivas de procesamiento de listas como cons, carycdr de sus progenitores Lisp. Scheme utiliza variables escritas de forma estricta pero dinámica y admite procedimientos de primera clase . Por tanto, los procedimientos pueden asignarse como valores a variables o pasarse como argumentos a procedimientos.
Esta sección se concentra principalmente en las características innovadoras del lenguaje, incluidas las características que distinguen a Scheme de otros Lisps. A menos que se indique lo contrario, las descripciones de las características se relacionan con el estándar R5RS.
En los ejemplos proporcionados en esta sección, la notación "===> resultado" se usa para indicar el resultado de evaluar la expresión en la línea inmediatamente anterior. Esta es la misma convención utilizada en R5RS.
Características de diseño fundamentales
Esta subsección describe las características de Scheme que lo han distinguido de otros lenguajes de programación desde sus inicios. Estos son los aspectos de Scheme que más influyen en cualquier producto del lenguaje Scheme, y son los aspectos que comparten todas las versiones del lenguaje de programación Scheme, desde 1973 en adelante.
Minimalismo
Scheme es un lenguaje muy simple, mucho más fácil de implementar que muchos otros lenguajes de poder expresivo comparable . [18] Esta facilidad es atribuible al uso del cálculo lambda para derivar gran parte de la sintaxis del lenguaje de formas más primitivas. Por ejemplo, de las 23 construcciones sintácticas basadas en expresión s definidas en el estándar R5RS Scheme, 14 se clasifican como formas derivadas o de biblioteca, que pueden escribirse como macros que involucran formas más fundamentales, principalmente lambda. Como dice R5RS (R5RS sec. 3.1): "La más fundamental de las construcciones de enlace variable es la expresión lambda, porque todas las demás construcciones de enlace variable se pueden explicar en términos de expresiones lambda". [4]
- Formas fundamentales : define, lambda, quote, if, define-syntax, let-syntax, letrec-syntax, syntax-rules, set!
- Formas derivadas : do, let, let *, letrec, cond, case y, or, begin, named let, delay, unquote, unquote-splicing, quasiquote
Ejemplo: una macro para implementar let
como una expresión usando lambda
para realizar los enlaces de variables.
( define-syntax let ( syntax-rules () (( let (( var expr ) ... ) body ... ) (( lambda ( var ... ) body ... ) expr ... ))))
Por lo tanto, usar let
como se define anteriormente una implementación de Scheme reescribiría " (let ((a 1)(b 2)) (+ b a))
" como " ((lambda (a b) (+ b a)) 1 2)
", lo que reduce la tarea de implementación a la de codificar instancias de procedimientos.
En 1998, Sussman y Steele comentaron que el minimalismo de Scheme no era un objetivo de diseño consciente, sino el resultado no deseado del proceso de diseño. "De hecho, estábamos tratando de construir algo complicado y descubrimos, por casualidad, que habíamos diseñado accidentalmente algo que cumplía con todos nuestros objetivos pero que era mucho más simple de lo que pretendíamos ... nos dimos cuenta de que el cálculo lambda, un formalismo pequeño y simple, podría servir como el núcleo de un lenguaje de programación poderoso y expresivo ". [8]
Alcance léxico
Como la mayoría de los lenguajes de programación modernos y a diferencia de Lisps anteriores como Maclisp , Scheme tiene un ámbito léxico: todos los enlaces de variables posibles en una unidad de programa se pueden analizar leyendo el texto de la unidad de programa sin tener en cuenta los contextos en los que se puede llamar. Esto contrasta con el alcance dinámico que era característico de los primeros dialectos Lisp, debido a los costos de procesamiento asociados con los métodos primitivos de sustitución textual utilizados para implementar algoritmos de alcance léxico en compiladores e intérpretes de la época. En esos Lisps, era perfectamente posible que una referencia a una variable libre dentro de un procedimiento se refiriera a enlaces bastante distintos externos al procedimiento, dependiendo del contexto de la llamada.
El ímpetu para incorporar el alcance léxico, que era un modelo de alcance inusual a principios de la década de 1970, en su nueva versión de Lisp, provino de los estudios de Sussman sobre ALGOL . Sugirió que los mecanismos de alcance léxico similares a ALGOL ayudarían a realizar su objetivo inicial de implementar el modelo Actor de Hewitt en Lisp. [8]
Las ideas clave sobre cómo introducir el alcance léxico en un dialecto Lisp se popularizaron en el documento Lambda de 1975 de Sussman y Steele, "Scheme: An Interpreter for Extended Lambda Calculus", [19] donde adoptaron el concepto de cierre léxico (en la página 21 ), que había sido descrito en un Memo de AI en 1970 por Joel Moses , quien atribuyó la idea a Peter J. Landin . [20]
Cálculo lambda
La notación matemática de Alonzo Church , el cálculo lambda, ha inspirado el uso de "lambda" de Lisp como palabra clave para introducir un procedimiento, además de influir en el desarrollo de técnicas de programación funcional que implican el uso de funciones de orden superior en Lisp. Pero los primeros Lisps no eran expresiones adecuadas del cálculo lambda debido a su tratamiento de variables libres . [8]
Un sistema lambda formal tiene axiomas y una regla de cálculo completa. Es útil para el análisis mediante herramientas y lógica matemática. En este sistema, el cálculo puede verse como una deducción direccional. La sintaxis del cálculo lambda sigue las expresiones recursivas de x, y, z, ..., paréntesis, espacios, el punto y el símbolo λ. [21] La función del cálculo lambda incluye: Primero, servir como punto de partida de una poderosa lógica matemática. En segundo lugar, puede reducir el requisito de que los programadores consideren los detalles de implementación, porque puede usarse para imitar la evaluación de la máquina. Finalmente, el cálculo lambda creó una metateoría sustancial. [22]
La introducción del alcance léxico resolvió el problema haciendo una equivalencia entre algunas formas de notación lambda y su expresión práctica en un lenguaje de programación de trabajo. Sussman y Steele demostraron que el nuevo lenguaje podría usarse para derivar elegantemente toda la semántica imperativa y declarativa de otros lenguajes de programación, incluidos ALGOL y Fortran , y el alcance dinámico de otros Lisps, mediante el uso de expresiones lambda no como simples instancias de procedimientos sino como "control estructuras y modificadores del entorno ". [23] Introdujeron el estilo de continuación-paso junto con su primera descripción de Scheme en el primero de los artículos Lambda, y en artículos posteriores, procedieron a demostrar el poder bruto de este uso práctico del cálculo lambda.
Estructura de bloque
Scheme hereda su estructura de bloques de lenguajes estructurados de bloques anteriores, particularmente ALGOL . En el Esquema, los bloques son ejecutados por tres construcciones de unión : let
, let*
y letrec
. Por ejemplo, la siguiente construcción crea un bloque en el que un símbolo llamado var
está vinculado al número 10:
( define var "ganso" ) ;; Cualquier referencia a var aquí estará vinculada a "goose" ( let (( var 10 )) ;; las declaraciones van aquí. Cualquier referencia a var aquí estará vinculada a 10. ) ;; Cualquier referencia a var aquí estará vinculada a "goose"
Los bloques se pueden anidar para crear estructuras de bloques arbitrariamente complejas de acuerdo con las necesidades del programador. El uso de la estructuración de bloques para crear enlaces locales alivia el riesgo de colisión de espacios de nombres que de otro modo podría ocurrir.
Una variante de let
, let*
permite que los enlaces se refieran a variables definidas anteriormente en la misma construcción, así:
( let * (( var1 10 ) ( var2 ( + var1 12 ))) ;; Pero la definición de var1 no podría referirse a var2 )
La otra variante, letrec
está diseñada para permitir que los procedimientos recursivos se unan entre sí.
;; Cálculo de las secuencias masculinas y femeninas de Hofstadter como una lista de pares( definir ( hofstadter-masculino-femenino n ) ( letrec (( femenino ( lambda ( n ) ( if ( = n 0 ) 1 ( - n ( masculino ( femenino ( - n 1 ))))))) ( masculino ( lambda ( n ) ( si ( = n 0 ) 0 ( - n ( mujer ( hombre ( - n 1 )))))))) ( let loop (( i 0 )) ( if ( > i n ) ' () ( contras ( contras ( mujer i ) ( hombre i )) ( bucle ( + i 1 )))))))( hofstadter-hombre-mujer 8 )===> (( 1 . 0 ) ( 1 . 0 ) ( 2 . 1 ) ( 2 . 2 ) ( 3 . 2 ) ( 3 . 3 ) ( 4 . 4 ) ( 5 . 4 ) ( 5 . 5 ) )
(Consulte las secuencias masculinas y femeninas de Hofstadter para conocer las definiciones utilizadas en este ejemplo).
Todos los procedimientos enlazados en un solo letrec
pueden referirse unos a otros por su nombre, así como a valores de variables definidas anteriormente en el mismo letrec
, pero pueden no referirse a valores definidos más adelante en el mismo letrec
.
Una variante de let
la forma "named let" tiene un identificador después de la let
palabra clave. Esto vincula las variables let al argumento de un procedimiento cuyo nombre es el identificador dado y cuyo cuerpo es el cuerpo de la forma let. El cuerpo se puede repetir como se desee llamando al procedimiento. El let con nombre se usa ampliamente para implementar la iteración.
Ejemplo: un contador simple
( let loop (( n 1 )) ( if ( > n 10 ) ' () ( cons n ( loop ( + n 1 )))))===> ( 1 2 3 4 5 6 7 8 9 10 )
Como cualquier procedimiento en Scheme, el procedimiento creado en el let nombrado es un objeto de primera clase.
Recursión de cola adecuada
Scheme tiene una construcción de iteración do
, pero es más idiomático en Scheme usar la recursividad de cola para expresar iteración . Se requieren implementaciones de Scheme que cumplan con los estándares para optimizar las llamadas de cola a fin de admitir un número ilimitado de llamadas de cola activas (R5RS sec. 3.5) [4] —una propiedad que el informe de Scheme describe como recursión de cola adecuada— lo que hace que sea seguro para los programadores de Scheme escribir algoritmos iterativos usando estructuras recursivas, que a veces son más intuitivas. Los procedimientos recursivos de cola y el formulario con nombrelet
brindan soporte para la iteración usando la recursividad de cola.
;; Construyendo una lista de cuadrados del 0 al 9: ;; Nota: el bucle es simplemente un símbolo arbitrario que se utiliza como etiqueta. Cualquier símbolo servirá.( define ( lista-de-cuadrados n ) ( let loop (( i n ) ( res ' ())) ( if ( < i 0 ) res ( loop ( - i 1 ) ( cons ( * i i ) res )) )))( lista de cuadrados 9 ) ===> ( 0 1 4 9 16 25 36 49 64 81 )
Continuaciones de primera clase
Las continuaciones en Scheme son objetos de primera clase . Scheme proporciona el procedimiento call-with-current-continuation
(también conocido como call/cc
) para capturar la continuación actual empaquetándola como un procedimiento de escape vinculado a un argumento formal en un procedimiento proporcionado por el programador. (R5RS sec. 6.4) [4] Las continuaciones de primera clase permiten al programador crear construcciones de control no locales como iteradores , corrutinas y retroceso .
Las continuaciones se pueden utilizar para emular el comportamiento de declaraciones de retorno en lenguajes de programación imperativos. La siguiente función find-first
, función func
y lista dadas lst
, devuelve el primer elemento x
en lst
tal que (func x)
devuelve verdadero.
( define ( buscar-primero func lst ) ( llamada-con-continuación-actual ( lambda ( retorno-inmediatamente ) ( para-cada ( lambda ( x ) ( if ( func x ) ( retorno-inmediatamente x ))) lst ) # f )))( Encontrar-primero número entero? ' ( 1 /2 3 /4 5,6 7 8 /9 10 11 )) ===> 7 ( encontrar-primero cero? ' ( 1 2 3 4 )) ===> #f
El siguiente ejemplo, un rompecabezas de programador tradicional, muestra que Scheme puede manejar continuaciones como objetos de primera clase, vinculándolos a variables y pasándolos como argumentos a procedimientos.
( let * (( yin (( lambda ( cc ) ( mostrar "@" ) cc ) ( llamada-con-continuación-actual ( lambda ( c ) c )))) ( yang (( lambda ( cc ) ( mostrar "* " ) cc ) ( llamada-con-continuación-actual ( lambda ( c ) c ))))) ( yin yang ))
Cuando se ejecuta, este código muestra una secuencia de conteo: @*@**@***@****@*****@******@*******@********...
A diferencia de Common Lisp, todos los datos y procedimientos en Scheme comparten un espacio de nombres común, mientras que en Common Lisp las funciones y los datos tienen espacios de nombres separados, lo que hace posible que una función y una variable tengan el mismo nombre y requieran una notación especial para referirse a un funcionan como un valor. Esto a veces se conoce como la distinción " Lisp-1 vs. Lisp-2 ", refiriéndose al espacio de nombres unificado de Scheme y los espacios de nombres separados de Common Lisp. [24]
En Scheme, las mismas primitivas que se usan para manipular y vincular datos se pueden usar para vincular procedimientos. No hay equivalente de Common Lisp defun
y #'
primitivas.
;; Variable ligada a un número: ( defina f 10 ) f ===> 10 ;; Mutación (alteración del valor límite) ( set! F ( + f f 6 )) f ===> 26 ;; Asignar un procedimiento a la misma variable: ( set! F ( lambda ( n ) ( + n 12 ))) ( f 6 ) ===> 18 ;; Asignar el resultado de una expresión a la misma variable: ( set! F ( f 1 )) f ===> 13 ;; programación funcional: ( aplicar + ' ( 1 2 3 4 5 6 )) ===> 21 ( set! f ( lambda ( n ) ( + n 100 ))) ( mapa f ' ( 1 2 3 )) === > ( 101 102 103 )
Estándares de implementación
Esta subsección documenta las decisiones de diseño que se han tomado a lo largo de los años y que le han dado a Scheme un carácter particular, pero que no son el resultado directo del diseño original.
Torre numérica
Scheme especifica un conjunto comparativamente completo de tipos de datos numéricos que incluyen tipos complejos y racionales , que se conoce en Scheme como la torre numérica (R5RS sec. 6.2 [4] ). El estándar los trata como abstracciones y no compromete al implementador a ninguna representación interna particular.
Los números pueden tener la calidad de la exactitud. Un número exacto sólo puede producirse mediante una secuencia de operaciones exactas que involucran a otros números exactos; por lo tanto, la inexactitud es contagiosa. El estándar especifica que dos implementaciones cualesquiera deben producir resultados equivalentes para todas las operaciones que dan como resultado números exactos.
Previsto por la norma procedimientos R5RS exact->inexact
y inexact->exact
que pueden ser utilizados para cambiar la exactitud de un número. inexact->exact
produce "el número exacto numéricamente más cercano al argumento". exact->inexact
produce "el número inexacto que es numéricamente más cercano al argumento". El estándar R6RS omite estos procedimientos del informe principal, pero los especifica como procedimientos de compatibilidad R5RS en la biblioteca estándar (rnrs r5rs (6)).
En el estándar R5RS, no se requiere que las implementaciones de Scheme implementen la torre numérica completa, pero deben implementar "un subconjunto coherente consistente con los propósitos de la implementación y el espíritu del lenguaje Scheme" (R5RS sec. 6.2.3). [4] El nuevo estándar R6RS requiere la implementación de toda la torre, y "objetos enteros exactos y objetos de números racionales exactos de tamaño y precisión prácticamente ilimitados, e implementar ciertos procedimientos ... para que siempre devuelvan resultados exactos cuando se les dan argumentos exactos "(R6RS sec. 3.4, sec. 11.7.1). [9]
Ejemplo 1: aritmética exacta en una implementación que admite números complejos racionales exactos.
;; Suma de tres números reales racionales y dos números complejos racionales ( definir x ( + 1 /3 1 /4 -1 / 5 -1 / 3i 405 /50 + 2 / 3i )) x ===> 509 /60 + 1 / 3i ;; Verifique la exactitud. ( ¿exacto? x ) ===> #t
Ejemplo 2: Misma aritmética en una implementación que no admite números racionales exactos ni números complejos, pero acepta números reales en notación racional.
;; Suma de cuatro números reales racionales ( definir xr ( + 1 /3 1 /4 -1 / 5 405 /50 )) ;; Suma de dos números reales racionales ( definir xi ( + -1 / 3 2 /3 )) xr ===> 8,48333333333333 xi ===> ,333333333333333 ;; Verifique la exactitud. ( ¿exacto? xr ) ===> #f ( exacto? xi ) ===> #f
Ambas implementaciones cumplen con el estándar R5RS pero la segunda no cumple con R6RS porque no implementa la torre numérica completa.
Evaluación retrasada
Scheme apoya la evaluación retrasada a través del delay
formulario y el procedimiento force
.
( define un 10 ) ( define eval-aplus2 ( delay ( + a 2 ))) ( set! a 20 ) ( force eval-aplus2 ) ===> 22 ( define eval-aplus50 ( delay ( + a 50 ))) ( let (( a 8 )) ( forzar eval-aplus50 )) ===> 70 ( set! a 100 ) ( forzar eval-aplus2 ) ===> 22
El contexto léxico de la definición original de la promesa se conserva y su valor también se conserva después del primer uso de force
. La promesa solo se evalúa una vez.
Estas primitivas, que producen o manejan valores conocidos como promesas , se pueden usar para implementar construcciones avanzadas de evaluación perezosa , como flujos . [25]
En el estándar R6RS, estos ya no son primitivos, sino que se proporcionan como parte de la biblioteca de compatibilidad R5RS (rnrs r5rs (6)).
En R5RS, se da una implementación sugerida de delay
y force
, implementando la promesa como un procedimiento sin argumentos (un procesador ) y usando memoization para garantizar que solo se evalúe una vez, independientemente del número de veces que force
se llame (R5RS sec. 6.4 ). [4]
SRFI 41 permite la expresión de secuencias finitas e infinitas con una economía extraordinaria. Por ejemplo, esta es una definición de la secuencia de fibonacci usando las funciones definidas en SRFI 41: [25]
;; Defina la secuencia de Fibonacci: ( define fibs ( stream-cons 0 ( stream-cons 1 ( stream-map + fibs ( stream-cdr fibs ))))) ;; Calcule el centésimo número en la secuencia: ( stream-ref fibs 99 ) ===> 218922995834555169026
Orden de evaluación de los argumentos del procedimiento
La mayoría de Lisps especifican un orden de evaluación para los argumentos del procedimiento. Scheme no lo hace. El orden de evaluación, incluido el orden en el que se evalúa la expresión en el puesto de operador, puede ser elegido por una implementación llamada por llamada, y la única restricción es que "el efecto de cualquier evaluación concurrente del operador y las expresiones de los operandos están limitadas a ser coherentes con algún orden secuencial de evaluación ". (R5RS sec. 4.1.3) [4]
( let (( ev ( lambda ( n ) ( mostrar "Evaluando" ) ( mostrar ( if ( procedimiento? n ) "procedimiento" n )) ( nueva línea ) n ))) (( ev + ) ( ev 1 ) ( ev 2 ))) ===> 3
ev es un procedimiento que describe el argumento que se le pasa y luego devuelve el valor del argumento. A diferencia de otros Lisps, la aparición de una expresión en la posición de operador (el primer elemento) de una expresión de Scheme es bastante legal, siempre que el resultado de la expresión en la posición de operador sea un procedimiento.
Al llamar al procedimiento "+" para sumar 1 y 2, las expresiones (ev +), (ev 1) y (ev 2) pueden evaluarse en cualquier orden, siempre que el efecto no sea como si fueran evaluadas en paralelo. . Por lo tanto, las siguientes tres líneas pueden mostrarse en cualquier orden mediante el esquema estándar cuando se ejecuta el código de ejemplo anterior, aunque el texto de una línea no se puede intercalar con otra porque eso violaría la restricción de evaluación secuencial.
- Evaluando 1
- Evaluando 2
- Procedimiento de evaluación
Macros higiénicas
En el estándar R5RS y también en informes posteriores, la sintaxis de Scheme se puede ampliar fácilmente a través del sistema de macros. El estándar R5RS introdujo un poderoso sistema macro higiénico que permite al programador agregar nuevas construcciones sintácticas al lenguaje usando un sublenguaje de coincidencia de patrones simple (R5RS sec 4.3). [4] Antes de esto, el macro sistema higiénico había sido relegado a un apéndice del estándar R4RS, como un sistema de "alto nivel" junto con un macro sistema de "bajo nivel", los cuales fueron tratados como extensiones del Esquema en lugar de un parte esencial del idioma. [26]
Las implementaciones del macro sistema higiénico, también llamado syntax-rules
, son necesarias para respetar el alcance léxico del resto de la lengua. Esto está asegurado por reglas especiales de nomenclatura y alcance para la expansión de macros y evita errores de programación comunes que pueden ocurrir en los sistemas de macros de otros lenguajes de programación. R6RS especifica un sistema de transformación más sofisticado syntax-case
, que ha estado disponible como una extensión de lenguaje del esquema R5RS durante algún tiempo.
;; Defina una macro para implementar una variante de "si" con una expresión múltiple ;; rama verdadera y no rama falsa. ( define-syntax when ( syntax-rules () (( when pred exp exps ... ) ( if pred ( begin exp exps ... )))))
Las invocaciones de macros y procedimientos se parecen mucho (ambas son expresiones-s) pero se tratan de manera diferente. Cuando el compilador encuentra una expresión-s en el programa, primero verifica si el símbolo está definido como una palabra clave sintáctica dentro del ámbito léxico actual. Si es así, intenta expandir la macro, tratando los elementos en la cola de la expresión-s como argumentos sin compilar código para evaluarlos, y este proceso se repite de forma recursiva hasta que no quedan invocaciones de macro. Si no es una palabra clave sintáctica, el compilador compila código para evaluar los argumentos en la cola de la expresión-s y luego para evaluar la variable representada por el símbolo al comienzo de la expresión-s y llamarla como un procedimiento con el las expresiones de cola evaluadas que se le pasan como argumentos reales.
La mayoría de las implementaciones de Scheme también proporcionan sistemas macro adicionales. Entre los más populares se encuentran los cierres sintácticos , las macros de cambio de nombre explícitas y define-macro
un sistema de macros no higiénico similar al defmacro
sistema proporcionado en Common Lisp .
La incapacidad de especificar si una macro es higiénica o no es una de las deficiencias del macro sistema. Los modelos alternativos de expansión, como los conjuntos de osciloscopios, proporcionan una solución potencial. [27]
Entornos y evaluación
Antes de R5RS, Scheme no tenía un equivalente estándar del eval
procedimiento que es omnipresente en otros Lisps, aunque el primer papel Lambda se describió evaluate
como "similar a la función LISP EVAL" [19] y el primer informe revisado en 1978 lo reemplazó con enclose
, que tomó dos argumentos. Los informes segundo, tercero y cuarto revisados omitieron cualquier equivalente de eval
.
La razón de esta confusión es que en Scheme con su alcance léxico, el resultado de evaluar una expresión depende de dónde se evalúe. Por ejemplo, no está claro si el resultado de evaluar la siguiente expresión debería ser 5 o 6: [28]
( dejar (( nombre '+ )) ( dejar (( + * )) ( evaluar ( lista nombre 2 3 ))))
Si se evalúa en el entorno externo, donde name
se define, el resultado es la suma de los operandos. Si se evalúa en el entorno interno, donde el símbolo "+" se ha vinculado al valor del procedimiento "*", el resultado es el producto de los dos operandos.
R5RS resuelve esta confusión especificando tres procedimientos que devuelven entornos y proporcionando un procedimiento eval
que toma una expresión s y un entorno y evalúa la expresión en el entorno proporcionado. (R5RS sec. 6.5) [4] R6RS amplía esto proporcionando un procedimiento llamado environment
mediante el cual el programador puede especificar exactamente qué objetos importar al entorno de evaluación.
Con un esquema moderno (generalmente compatible con R5RS) para evaluar esta expresión, es necesario definir una función evaluate
que pueda verse así:
( definir ( evaluar expr ) ( eval expr ( interacción-entorno )))
interaction-environment
es el entorno global del intérprete.
Tratamiento de valores no booleanos en expresiones booleanas
En la mayoría de los dialectos de Lisp, incluido Common Lisp, por convención el valor se NIL
evalúa como el valor falso en una expresión booleana. En Scheme, desde el estándar IEEE en 1991, [3] todos los valores excepto #f, incluido NIL
el equivalente en Scheme que se escribe como '(), se evalúan con el valor verdadero en una expresión booleana. (R5RS sec. 6.3.1) [4]
Donde la constante que representa el valor booleano de verdadero está T
en la mayoría de Lisps, en Scheme lo es #t
.
Disjunción de tipos de datos primitivos
En Scheme, los tipos de datos primitivos están separados. Sólo uno de los siguientes predicados puede ser cierto de cualquier objeto Esquema: boolean?
, pair?
, symbol?
, number?
, char?
, string?
, vector?
, port?
, procedure?
. (R5RS, sección 3.2) [4]
Dentro del tipo de datos numéricos, por el contrario, los valores numéricos se superponen. Por ejemplo, un valor entero satisface todos los integer?
, rational?
, real?
, complex?
y number?
predicados al mismo tiempo. (R5RS, sección 6.2) [4]
Predicados de equivalencia
Scheme tiene tres tipos diferentes de equivalencia entre objetos arbitrarios denotados por tres predicados de equivalencia diferentes , operadores relacionales para probar la igualdad eq?
, eqv?
y equal?
:
eq?
evalúa a a#f
menos que sus parámetros representen el mismo objeto de datos en la memoria;eqv?
es generalmente lo mismo queeq?
pero trata los objetos primitivos (por ejemplo, caracteres y números) especialmente para que los números que representan el mismo valor seaneqv?
incluso si no se refieren al mismo objeto;equal?
compara estructuras de datos como listas, vectores y cadenas para determinar si tienen una estructura yeqv?
contenido congruentes (R5RS sec. 6.1) [4]
Las operaciones de equivalencia dependientes del tipo también existen en Scheme: string=?
y string-ci=?
comparar dos cadenas (la última realiza una comparación independiente del caso); char=?
y char-ci=?
comparar personajes; =
compara números. [4]
Comentarios
Hasta el estándar R5RS, el comentario estándar en Scheme era un punto y coma, lo que hace que el resto de la línea sea invisible para Scheme. Numerosas implementaciones han admitido convenciones alternativas que permiten que los comentarios se extiendan por más de una línea, y el estándar R6RS permite dos de ellas: una expresión-s completa se puede convertir en un comentario (o "comentar") precediéndola con #;
(introducido en SRFI 62 [29] ) y se puede producir un comentario de varias líneas o un "comentario de bloque" rodeando el texto con #|
y |#
.
De entrada y salida
La entrada y salida de Scheme se basa en el tipo de datos del puerto . (R5RS sec 6.6) [4] R5RS define dos puertos predeterminados, accesibles con los procedimientos current-input-port
y current-output-port
, que corresponden a las nociones de Unix de entrada estándar y salida estándar . La mayoría de las implementaciones también proporcionan current-error-port
. La redirección de entrada y salida estándar es compatible con el estándar, mediante procedimientos estándar como with-input-from-file
y with-output-to-file
. La mayoría de las implementaciones proporcionan puertos de cadena con capacidades de redirección similares, lo que permite realizar muchas operaciones normales de entrada y salida en búferes de cadena en lugar de archivos, utilizando los procedimientos descritos en SRFI 6. [30] El estándar R6RS especifica procedimientos de puerto mucho más sofisticados y capaces y muchos nuevos tipos de puerto.
Los siguientes ejemplos están escritos en un estricto esquema R5RS.
Ejemplo 1: con salida predeterminada a (puerto de salida actual):
( let (( hola0 ( lambda () ( mostrar "Hola mundo" ) ( nueva línea )))) ( hola0 ))
Ejemplo 2: como 1, pero usando un argumento de puerto opcional para los procedimientos de salida
( let (( hola1 ( lambda ( p ) ( mostrar "Hola mundo" p ) ( nueva línea p )))) ( hola1 ( puerto de salida actual )))
Ejemplo 3: como 1, pero la salida se redirige a un archivo recién creado
;; NB: with-output-to-file es un procedimiento opcional en R5RS ( let (( hello0 ( lambda () ( display "Hello world" ) ( newline )))) ( with-output-to-file "helloworldoutputfile" hello0 ) )
Ejemplo 4: como 2, pero con un archivo explícito abierto y un puerto cerrado para enviar la salida al archivo
( Dejar que (( hello1 ( lambda ( p ) ( pantalla "Hola mundo" p ) ( nueva línea p ))) ( salida de puertos ( -salida abierta en archivos "helloworldoutputfile" ))) ( hello1 salida de puertos ) ( cerca de salida -port salida-puerto ))
Ejemplo 5: como 2, pero con el uso de call-with-output-file para enviar la salida a un archivo.
( let (( hello1 ( lambda ( p ) ( mostrar "Hola mundo" p ) ( nueva línea p )))) ( llamada-con-archivo-de-salida "helloworldoutputfile" hola1 ))
Se proporcionan procedimientos similares para la entrada. El esquema R5RS proporciona los predicados input-port?
y output-port?
. Para la entrada y salida de caracteres, write-char
, read-char
, peek-char
y char-ready?
se proporcionan. Para escribir y leer expresiones de Scheme, Scheme proporciona read
y write
. En una operación de lectura, el resultado devuelto es el objeto de fin de archivo si el puerto de entrada ha llegado al final del archivo, y esto se puede probar usando el predicado eof-object?
.
Además del estándar, SRFI 28 define un procedimiento de formateo básico que se asemeja a la format
función de Common Lisp , después de lo cual recibe su nombre. [31]
Redefinición de procedimientos estándar
En Scheme, los procedimientos están vinculados a variables. En R5RS, el estándar de lenguaje exigía formalmente que los programas pudieran cambiar las vinculaciones variables de los procedimientos incorporados, redefiniéndolos de manera efectiva. (R5RS "Cambios de idioma") [4] Por ejemplo, uno puede ampliar +
para aceptar cadenas y números redefiniéndolo:
( set! + ( let (( original + + )) ( lambda args ( apply ( if ( or ( null? args ) ( string? ( car args ))) string-append original + ) args )))) ( + 1 2 3 ) ===> 6 ( + "1" "2" "3" ) ===> "123"
En R6RS, todos los enlaces, incluidos los estándar, pertenecen a alguna biblioteca y todos los enlaces exportados son inmutables. (R6RS sec 7.1) [9] Debido a esto, se prohíbe la redefinición de procedimientos estándar por mutación. En cambio, es posible importar un procedimiento diferente bajo el nombre de uno estándar, que en efecto es similar a la redefinición.
Nomenclatura y convenciones de nomenclatura
En el esquema estándar, los procedimientos que convierten de un tipo de datos a otro contienen la cadena de caracteres "->" en su nombre, los predicados terminan con un "?" Y los procedimientos que cambian el valor de los datos ya asignados terminan con un "!". Los programadores de Scheme suelen seguir estas convenciones.
En contextos formales como los estándares de Scheme, la palabra "procedimiento" se usa con preferencia a "función" para referirse a una expresión lambda o procedimiento primitivo. En el uso normal, las palabras "procedimiento" y "función" se utilizan indistintamente. La aplicación del procedimiento a veces se denomina formalmente combinación .
Como en otros Lisps, el término " procesador " se usa en Scheme para referirse a un procedimiento sin argumentos. El término "recursividad de cola adecuada" se refiere a la propiedad de todas las implementaciones de Scheme, que realizan una optimización de llamadas de cola para admitir un número indefinido de llamadas de cola activas .
La forma de los títulos de los documentos de estándares desde R3RS, " Informe n revisado sobre el esquema de lenguaje algorítmico", es una referencia al título del documento estándar ALGOL 60 , "Informe revisado sobre el lenguaje algorítmico Algol 60", la página Resumen de R3RS se modela de cerca en la página Resumen del Informe ALGOL 60. [32] [33]
Revisión de formularios y procedimientos estándar
El lenguaje se define formalmente en los estándares R5RS (1998) y R6RS (2007). Describen "formas" estándar: palabras clave y sintaxis adjunta, que proporcionan la estructura de control del lenguaje, y procedimientos estándar que realizan tareas comunes.
Formas estándar
Esta tabla describe los formularios estándar en Scheme. Algunas formas aparecen en más de una fila porque no se pueden clasificar fácilmente en una sola función en el idioma.
Los formularios marcados con "L" en esta tabla se clasifican como formularios de "biblioteca" derivados en el estándar y a menudo se implementan como macros utilizando formularios más fundamentales en la práctica, lo que hace que la tarea de implementación sea mucho más fácil que en otros lenguajes.
Propósito | Formularios |
---|---|
Definición | definir |
Construcciones vinculantes | lambda, hacer (L), dejar (L), dejar * (L), letrec (L) |
Evaluación condicional | si, cond (L), caso (L) y (L), o (L) |
Evaluación secuencial | empezar (*) |
Iteración | lambda, hacer (L), llamado let (L) |
Extensión sintáctica | define-syntax, let-syntax, letrec-syntax, syntax-rules (R5RS), syntax-case (R6RS) |
Cotización | comillas ('), unquote (,), quasiquote (`), unquote-splicing (, @) |
Asignación | ¡colocar! |
Evaluación retrasada | retraso (L) |
Tenga en cuenta que begin
se define como una sintaxis de biblioteca en R5RS, pero el expansor debe conocerla para lograr la funcionalidad de empalme. En R6RS ya no es una sintaxis de biblioteca.
Procedimientos estándar
Las siguientes dos tablas describen los procedimientos estándar en el esquema R5RS. R6RS es mucho más extenso y un resumen de este tipo no sería práctico.
Algunos procedimientos aparecen en más de una fila porque no se pueden clasificar fácilmente en una sola función en el idioma.
Propósito | Procedimientos |
---|---|
Construcción | vector, make-vector, make-string, list |
Predicados de equivalencia | eq ?, eqv ?, ¿igual ?, cadena = ?, cadena-ci = ?, char = ?, char-ci =? |
Conversión de tipo | vector-> lista, lista-> vector, número-> cadena, cadena-> número, símbolo-> cadena, cadena-> símbolo, carácter-> entero, entero-> carácter, cadena-> lista, lista-> cadena |
Números | Ver tabla separada |
Instrumentos de cuerda | string ?, make-string, string, string-length, string-ref, string-set !, string = ?, string-ci = ?, string cadena-ci , cadena |
Caracteres | char ?, char = ?, char-ci = ?, char char-ci , char |
Vectores | make-vector, vector, vector ?, vector-length, vector-ref, vector-set !, vector-> list, list-> vector, vector-fill! |
Simbolos | símbolo-> cadena, cadena-> símbolo, símbolo? |
Pares y listas | par ?, cons, car, cdr, set-car !, set-cdr !, null ?, list ?, list, length, append, reverse, list-tail, list-ref, memq. memv. miembro, assq, assv, assoc, lista-> vector, vector-> lista, lista-> cadena, cadena-> lista |
Predicados de identidad | ¿booleano ?, ¿par ?, ¿símbolo ?, ¿número ?, ¿carácter ?, ¿cadena ?, ¿vector ?, ¿puerto ?, ¿procedimiento? |
Continuaciones | llamada-con-continuación-actual (llamada / cc), valores, llamada-con-valores, viento-dinámico |
Ambientes | eval, esquema-informe-entorno, entorno-nulo, entorno-interacción (opcional) |
De entrada y salida | display, newline, read, write, read-char, write-char, peek-char, char-ready ?, eof-object? abrir-archivo-entrada, abrir-archivo-salida, cerrar-puerto-entrada, cerrar-puerto-salida, puerto-entrada ?, puerto-salida ?, puerto-entrada-corriente, puerto-salida-corriente, llamar-con- archivo de entrada, llamada con archivo de salida, con entrada desde archivo (opcional), con salida a archivo (opcional) |
Interfaz del sistema | cargar (opcional), transcripción activada (opcional), transcripción desactivada (opcional) |
Evaluación retrasada | fuerza |
Programación funcional | procedimiento ?, aplicar, mapa, para-cada |
Booleanos | booleano? no |
Los procedimientos de cadenas y caracteres que contienen "-ci" en sus nombres realizan comparaciones independientes de mayúsculas y minúsculas entre sus argumentos: las versiones en mayúsculas y minúsculas del mismo carácter se consideran iguales.
Propósito | Procedimientos |
---|---|
Operadores aritméticos básicos | +, -, *, /, abs, cociente, resto, módulo, gcd, lcm, expt, sqrt |
Numeros racionales | numerador, denominador, racional ?, racionalizar |
Aproximación | piso, techo, truncar, redondo |
Exactitud | inexacto-> exacto, exacto-> inexacto, exacto ?, inexacto? |
Desigualdades | <, <=,>,> =, = |
Predicados varios | ¿cero ?, ¿negativo ?, ¿positivo? ¿impar? ¿incluso? |
Máximo y mínimo | máximo minimo |
Trigonometría | pecado, cos, bronceado, asin, acos, atan |
Exponenciales | exp, registro |
Números complejos | hacer-rectangular, hacer-polar, parte real, parte imag, magnitud, ángulo, complejo? |
De entrada y salida | número-> cadena, cadena-> número |
Predicados de tipo | ¿entero ?, ¿racional ?, ¿real ?, ¿complejo ?, ¿número? |
Las implementaciones de - y / que toman más de dos argumentos se definen pero se dejan opcionales en R5RS.
Solicitudes de esquema para la implementación
Debido al minimalismo de Scheme, muchos procedimientos comunes y formas sintácticas no están definidos por el estándar. Para mantener el lenguaje central pequeño pero facilitar la estandarización de las extensiones, la comunidad Scheme tiene un proceso de "Solicitud de esquema para la implementación" (SRFI) mediante el cual las bibliotecas de extensión se definen mediante una discusión cuidadosa de las propuestas de extensión. Esto promueve la portabilidad del código. Muchas de las SRFI son compatibles con todas o la mayoría de las implementaciones de Scheme.
Las SRFI con un apoyo bastante amplio en diferentes implementaciones incluyen: [34]
- 0: construcción de expansión condicional basada en características
- 1: biblioteca de listas
- 4: tipos de datos vectoriales numéricos homogéneos
- 6: puertos de cadena básicos
- 8: recibir, vinculante a múltiples valores
- 9: definición de tipos de registros
- 13: biblioteca de cadenas
- 14: biblioteca de juegos de caracteres
- 16: sintaxis para procedimientos de aridad variable
- 17: conjunto generalizado!
- 18: soporte de subprocesos múltiples
- 19: tipos de datos de tiempo y procedimientos
- 25: primitivas de matriz multidimensional
- 26: notación para especializar parámetros sin curry
- 27: fuentes de bits aleatorios
- 28: cadenas de formato básico
- 29: localización
- 30: comentarios multilínea anidados
- 31: un formulario especial para la evaluación recursiva
- 37: args-fold: un procesador de argumentos de programa
- 39: objetos de parámetro
- 41: arroyos
- 42: comprensiones ansiosas
- 43: biblioteca de vectores
- 45: primitivas para expresar algoritmos perezosos iterativos
- 60: enteros como bits
- 61: una cláusula cond más general
- 66: vectores de octetos
- 67: comparar procedimientos
Implementaciones
El diseño elegante y minimalista ha convertido a Scheme en un objetivo popular para diseñadores de idiomas, aficionados y educadores, y debido a su pequeño tamaño, el de un intérprete típico , también es una opción popular para sistemas integrados y secuencias de comandos . Esto ha dado como resultado decenas de implementaciones, [35] la mayoría de las cuales difieren tanto entre sí que la migración de programas de una implementación a otra es bastante difícil, y el tamaño pequeño del lenguaje estándar significa que escribir un programa útil de gran complejidad en Scheme estándar y portátil es casi imposible. [7] El estándar R6RS especifica un lenguaje mucho más amplio, en un intento de ampliar su atractivo para los programadores.
Casi todas las implementaciones proporcionan un bucle tradicional de lectura-evaluación-impresión estilo Lisp para desarrollo y depuración. Muchos también compilan programas Scheme en binarios ejecutables. Soporte para incrustar código de Scheme en programas escritos en otros idiomas también es común, como la relativa simplicidad del esquema para la implementación hace que sea una opción popular para la adición de capacidades de scripting para sistemas más grandes desarrolladas en lenguajes como C . Los intérpretes de Gambit , Chicken y Bigloo Scheme compilan Scheme en C, lo que hace que la incrustación sea particularmente fácil. Además, el compilador de Bigloo se puede configurar para generar código de bytes JVM , y también cuenta con un generador de código de bytes experimental para .NET .
Algunas implementaciones admiten funciones adicionales. Por ejemplo, Kawa y JScheme proporcionan integración con clases de Java, y los compiladores de Scheme to C a menudo facilitan el uso de bibliotecas externas escritas en C, hasta permitir la incrustación de código C real en la fuente de Scheme. Otro ejemplo es Pvts , que ofrece un conjunto de herramientas visuales para apoyar el aprendizaje de Scheme.
Uso
El esquema es ampliamente utilizado por varias [36] escuelas; en particular, varios cursos de introducción a la informática utilizan Scheme junto con el libro de texto Estructura e interpretación de programas informáticos (SICP). [37] Durante los últimos 12 años, PLT ha ejecutado el proyecto ProgramByDesign (anteriormente TeachScheme!), Que ha expuesto a cerca de 600 profesores de secundaria y miles de estudiantes de secundaria a la programación rudimentaria de Scheme. MIT vieja clase introducción a la programación 's 6.001 se enseñaba en el esquema, [38] A pesar de que 6.001 se ha sustituido por un curso más modernos, SICP sigue siendo enseñada en el MIT. [39] Del mismo modo, la clase introductoria en UC Berkeley , CS 61A, se impartió hasta 2011 en su totalidad en Scheme, salvo desviaciones menores en Logo para demostrar el alcance dinámico. Hoy, al igual que el MIT, Berkeley ha reemplazado el programa de estudios con una versión más moderna que se enseña principalmente en Python 3 , pero el programa de estudios actual todavía se basa en el plan de estudios anterior, y partes de la clase todavía se enseñan en Scheme. [40]
El libro de texto Cómo diseñar programas de Matthias Felleisen, actualmente en Northeastern University, es utilizado por algunos institutos de educación superior para sus cursos de introducción a la informática. Tanto la Northeastern University como el Worcester Polytechnic Institute utilizan Scheme exclusivamente para sus cursos introductorios Fundamentals of Computer Science (CS2500) e Introducción al diseño de programas (CS1101), respectivamente. [41] [42] Rose-Hulman usa Scheme en su curso más avanzado de conceptos de lenguaje de programación. [43] El curso básico de la Universidad de Brandeis , Estructura e interpretación de programas informáticos (COSI121b), también se imparte exclusivamente en Scheme por el científico informático teórico Harry Mairson . [44] La clase introductoria de la Universidad de Indiana , C211, se imparte íntegramente en Scheme. Una versión del curso a su propio ritmo, CS 61AS, sigue utilizando Scheme. [45] Los cursos de introducción a la informática en Yale y Grinnell College también se imparten en Scheme. [46] Paradigmas de diseño de programación, [47] un curso obligatorio para los estudiantes graduados en ciencias de la computación en la Northeastern University , también utiliza ampliamente Scheme. El antiguo curso introductorio de Ciencias de la Computación en la Universidad de Minnesota - Twin Cities, CSCI 1901, también usó Scheme como su idioma principal, seguido de un curso que introdujo a los estudiantes al lenguaje de programación Java; [48] sin embargo, siguiendo el ejemplo del MIT, el departamento reemplazó 1901 con el CSCI 1133 basado en Python, [49] mientras que la programación funcional se cubre en detalle en el curso del tercer semestre CSCI 2041. [50] En la industria del software, Tata Consultancy Services , la empresa de consultoría de software más grande de Asia, utiliza Scheme en su programa de capacitación de un mes para recién graduados universitarios. [ cita requerida ]
El esquema también se usa / se usó para lo siguiente:
- El lenguaje de especificación y semántica de estilo de documento (DSSSL), que proporciona un método para especificar hojas de estilo SGML , utiliza un subconjunto de esquema. [51]
- El conocido editor de gráficos de trama de código abierto GIMP utiliza TinyScheme como lenguaje de programación . [52]
- Guile ha sido adoptado por el proyecto GNU como su lenguaje de scripting oficial, y esa implementación de Scheme está incrustada en aplicaciones como GNU LilyPond y GnuCash como lenguaje de scripting para extensiones. Asimismo, Guile solía ser el lenguaje de programación para el entorno de escritorio GNOME , [53] y GNOME todavía tiene un proyecto que proporciona enlaces Guile a su pila de bibliotecas. [54] Hay un proyecto para incorporar Guile en GNU Emacs , el programa insignia de GNU, en sustitución del intérprete Emacs Lisp actual . [ cita requerida ]
- Synopsys utiliza Elk Scheme como lenguaje de programación para sus herramientas de tecnología CAD (TCAD) . [55]
- Shiro Kawai, programador senior de la película Final Fantasy: The Spirits Within , usó Scheme como lenguaje de programación para administrar el motor de renderizado en tiempo real. [56]
- Google App Inventor para Android usa Scheme, donde Kawa se usa para compilar el código Scheme hasta códigos de bytes para la máquina virtual Java que se ejecuta en dispositivos Android. [57]
Ver también
- Compilador de Stalin , un compilador de Scheme.
- Conceptos básicos de lenguajes de programación , otrolibro de textoclásico de ciencias de la computación .
- SXML , una representación ilustrativa de XML en Scheme que proporciona un enfoque sencillo para el procesamiento de datos XML en Scheme.
Referencias
- ^ "El lenguaje de programación del esquema" . MIT .
- ^ Common LISP: The Language, 2nd Ed., Guy L. Steele Jr. Digital Press; 1981. ISBN 978-1-55558-041-4 . "Common Lisp es un nuevo dialecto de Lisp, un sucesor de MacLisp, fuertemente influenciado por ZetaLisp y hasta cierto punto por Scheme e InterLisp".
- ^ a b 1178-1990 (Reaff 2008) Estándar IEEE para el lenguaje de programación del esquema. IEEE número de pieza STDPD14209, reafirmado por unanimidad en una reunión del Comité de Revisión de Normas de la Junta de Normas de IEEE-SA (RevCom), 26 de marzo de 2008 (punto 6.3 sobre las actas), actas de reafirmación consultadas en octubre de 2009. NOTA: este documento solo está disponible para su compra de IEEE y no está disponible en línea al momento de escribir este artículo (2009).
- ^ a b c d e f g h i j k l m n o p q Richard Kelsey; William Clinger; Jonathan Rees; et al. (Agosto de 1998). " 5 Informe revisado sobre el esquema de lenguaje algorítmico" . Computación simbólica y de orden superior . 11 (1): 7–105. doi : 10.1023 / A: 1010051815785 . S2CID 14069423 . Consultado el 9 de agosto de 2012 .
- ^ Shinn, Alex; Cowan, John; Gleckler, Arthur (julio de 2013). " 7 Informe revisado sobre el esquema de lenguaje algorítmico (R7RS)" . Consultado el 8 de noviembre de 2020 .
- ^ a b "R7RS final disponible" (PDF) . 2013-07-06.
- ^ a b c Will Clinger, Marc Feeley, Chris Hanson, Jonathan Rees y Olin Shivers (20 de agosto de 2009). "Declaración de posición (borrador) " . Comité Directivo del Esquema . Consultado el 9 de agosto de 2012 .CS1 maint: varios nombres: lista de autores ( enlace )
- ^ a b c d Sussman, Gerald Jay; Steele, Guy L. (1 de diciembre de 1998). "El primer informe sobre el esquema revisado". Computación simbólica y de orden superior . 11 (4): 399–404. doi : 10.1023 / A: 1010079421970 . S2CID 7704398 .
- ^ a b c d Sperber, Michael; Dybvig, R. Kent; Flatt, Matthew; Van Straaten, Anton; et al. (Agosto de 2007). " Informe revisado 6 sobre el esquema de lenguaje algorítmico (R6RS)" . Comité Directivo del Esquema . Consultado el 13 de septiembre de 2011 .
- ^ "Implementaciones R6RS" . r6rs.org . Consultado el 24 de noviembre de 2017 .
- ^ Abdulaziz Ghuloum (27 de octubre de 2007). "Bibliotecas R6RS y sistema de casos de sintaxis (psyntax)" . Esquema de Ikarus . Consultado el 20 de octubre de 2009 .
- ^ Mantener, Andrew W .; Dybvig, R. Kent (noviembre de 2014). "Una representación en tiempo de ejecución de los tipos de registros de esquema". Revista de programación funcional . 24 (6): 675–716. doi : 10.1017 / S0956796814000203 . S2CID 40001845 .
- ^ "Informe revisado ^ 6 sobre el esquema de lenguaje algorítmico, Apéndice E: cambios de idioma" . Comité Directivo del Esquema. 2007-09-26 . Consultado el 20 de octubre de 2009 .
- ^ "Electorado R6RS" . Comité Directivo del Esquema. 2007 . Consultado el 9 de agosto de 2012 .
- ^ Marc Feeley (compilación) (2007-10-26). "Intenciones de los implementadores sobre R6RS" . Scheme Steering Committee, lista de correo r6rs-discusion . Consultado el 9 de agosto de 2012 .
- ^ "Noveno borrador de R7RS disponible" (PDF) . 2013-04-15.
- ^ Will Clinger (10 de mayo de 2013). "extensión del período de votación" . Scheme Language Steering Committee, lista de distribución de informes de Scheme. Archivado desde el original el 21 de julio de 2013 . Consultado el 7 de julio de 2013 .
- ^ Laimplementación del Esquema 48 se llama así porque el intérprete fue escrito por Richard Kelsey y Jonathan Rees en 48 horas (6 al 7 de agosto de 1986. Ver Richard Kelsey; Jonathan Rees; Mike Sperber (10 de enero de 2008). "Manual de referencia del esquema incompleto 48 para la versión 1.8" . Jonathan Rees, s48.org . Consultado el 9 de agosto de 2012 .
- ^ a b Gerald Jay Sussman y Guy Lewis Steele Jr. (diciembre de 1975). "Esquema: un intérprete de cálculo Lambda extendido" . Memos AI . Laboratorio de IA del MIT . AIM-349. Archivado desde el original (posdata o PDF) el 10 de mayo de 2016 . Consultado el 9 de agosto de 2012 .
- ^ Joel Moses (junio de 1970), The Function of FUNCTION in LISP, or Why the FUNARG Problem Should Be Called the Environment Problem , hdl : 1721.1 / 5854 , AI Memo 199,
Una metáfora útil para la diferencia entre FUNCTION y QUOTE en LISP es Piense en QUOTE como una cobertura porosa o abierta de la función, ya que las variables libres escapan al entorno actual. FUNCIÓN actúa como una cubierta cerrada o no porosa (de ahí el término "cierre" utilizado por Landin). Por tanto, hablamos de expresiones Lambda "abiertas" (las funciones en LISP suelen ser expresiones Lambda) y expresiones Lambda "cerradas". [...] Mi interés en el problema del medio ambiente comenzó cuando Landin, que tenía un profundo conocimiento del problema, visitó el MIT durante 1966-67. Entonces me di cuenta de la correspondencia entre las listas FUNARG que son los resultados de la evaluación de expresiones Lambda "cerradas" en LISP y los cierres Lambda de ISWIM .
- ^ van Tonder, André (1 de enero de 2004). "Un cálculo Lambda para la computación cuántica". Revista SIAM de Computación . 33 (5): 1109-1135. arXiv : quant-ph / 0307150 . doi : 10.1137 / S0097539703432165 . S2CID 613571 .
- ^ Niehren, J .; Schwinghammer, J .; Smolka, G. (noviembre de 2006). "Un cálculo lambda concurrente con futuros" (PDF) . Informática Teórica . 364 (3): 338–356. doi : 10.1016 / j.tcs.2006.08.016 .
- ^ Gerald Jay Sussman y Guy Lewis Steele Jr. (marzo de 1976). "Lambda: el último imperativo" . Memos AI . Laboratorio de IA del MIT . AIM-353. Archivado desde el original (posdata o PDF) el 10 de mayo de 2016 . Consultado el 9 de agosto de 2012 .
- ^ Gabriel, Richard P .; Pitman, Kent (1988). "Problemas técnicos de la separación en celdas de función y celdas de valor" . Lisp y computación simbólica . 1 (1) (publicado en junio de 1988). págs. 81-101. doi : 10.1007 / BF01806178 . Consultado el 9 de agosto de 2012 .
- ^ a b Philip L. Bewig (24 de enero de 2008). "SRFI 41: Streams" . Los editores de SRFI, schemers.org . Consultado el 9 de agosto de 2012 .
- ^ William Clinger y Jonathan Rees, editores (1991). " 4 Informe revisado sobre el esquema de lenguaje algorítmico" . Punteros ACM Lisp . 4 (3): 1–55 . Consultado el 9 de agosto de 2012 .
- ^ Flatt, Matthew (2016). "Encuadernación como conjuntos de alcances". Actas del 43º Simposio anual ACM SIGPLAN-SIGACT sobre principios de lenguajes de programación . págs. 705–717. doi : 10.1145 / 2837614.2837620 . ISBN 978-1-4503-3549-2. S2CID 15401805 .
- ↑ Jonathan Rees, The Scheme of Things The June 1992 Meeting Archivado el 16 de julio de 2011 en la Wayback Machine (posdata), en Lisp Pointers, V (4), octubre-diciembre de 1992. Consultado el 9 de agosto de 2012.
- ^ Taylor Campbell (21 de julio de 2005). "SRFI 62: comentarios de expresión S" . Los editores de SRFI, schemers.org . Consultado el 9 de agosto de 2012 .
- ^ William D Clinger (1 de julio de 1999). "SRFI 6: Puertos de cadena básicos" . Los editores de SRFI, schemers.org . Consultado el 9 de agosto de 2012 .
- ^ Scott G. Miller (25 de junio de 2002). "SRFI 28: Cadenas de formato básico" . Los editores de SRFI, schemers.org . Consultado el 9 de agosto de 2012 .
- ^ JW Backus; FL Bauer; J.Green; C. Katz; J. McCarthy P. Naur; et al. (Enero-abril de 1960). "Informe revisado sobre el lenguaje algorítmico Algol 60" . Numerische Mathematik, Comunicaciones de la ACM y Revista de la British Computer Society . Consultado el 9 de agosto de 2012 .
- ^ Jonathan Rees; William Clinger, eds. (Diciembre de 1986). "Informe revisado (3) sobre el esquema de lenguaje algorítmico (dedicado a la memoria de ALGOL 60)" . Avisos ACM SIGPLAN . 21 (12): 37–79. CiteSeerX 10.1.1.29.3015 . doi : 10.1145 / 15042.15043 . S2CID 43884422 . Consultado el 9 de agosto de 2012 .
- ^ "Sistemas de esquema de apoyo a las SRFI" . Los editores de SRFI, schemers.org. 2009-08-30 . Consultado el 9 de agosto de 2012 .
- ^ 75 implementaciones conocidas de Scheme se enumeran por "esquema-faq-estándares" . Wiki de Esquema Comunitario. 2009-06-25 . Consultado el 20 de octubre de 2009 .
- ^ Ed Martin (20 de julio de 2009). "Lista de escuelas que utilizan el esquema" . Intrigantes Inc . Consultado el 20 de octubre de 2009 .
- ^ "Lista de escuelas que utilizan SICP" . MIT Press. 1999-01-26 . Consultado el 20 de octubre de 2009 .
- ^ Eric Grimson (primavera de 2005). "6.001 Estructura e interpretación de programas informáticos" . Material didáctico abierto del MIT . Consultado el 20 de octubre de 2009 .
- ^ Alex Vandiver; Nelson Elhage; et al. (Enero de 2009). "6.184 - Los zombis beben 6.001 con cafeína" . MIT CSAIL . Consultado el 20 de octubre de 2009 .
- ^ John DeNero (otoño de 2019). "Informática 61A, Berkeley" . Departamento de Ingeniería Eléctrica y Ciencias de la Computación, Berkeley . Consultado el 17 de diciembre de 2019 .
- ^ CS 2500: Fundamentos de la informática I , Northeastern University
- ^ CS 1101: Introducción al diseño de programas (A05): software del curso , Instituto Politécnico de Worcester
- ^ "CSSE 304: conceptos de lenguaje de programación" . Instituto de Tecnología Rose-Hulman .
- ^ "Spring 2021 CS121b Syllabus" (PDF) . Universidad de Brandeis .
- ^ https://berkeley-cs61as.github.io
- ^ Dana Angluin (otoño de 2009). "Introducción a la informática (CPSC 201)" . El zoológico, Departamento de Ciencias de la Computación de la Universidad de Yale . Consultado el 20 de octubre de 2009 .
- ^ "Lecturas del Curso de Paradigmas de Diseño de Programación CSG107" . Facultad de Informática y Ciencias de la Información de la Northeastern University. Otoño de 2009 . Consultado el 9 de agosto de 2012 .
- ^ Estructura de la programación informática que archivado el 19 de junio de 2010en Wayback Machine , Departamento de Ciencias de la Computación, Universidad de Minnesota, primavera de 2010 (consultado el 30 de enero de 2010).
- ^ Descripciones de cursos de clase obligatoria de CSci y otra información archivada el 25 de octubre de 2019 en Wayback Machine , Departamento de Ciencias de la Computación, Universidad de Minnesota (consultado el 25 de octubre de 2019)
- ^ CSCI 2041 — Comité de currículo de CSE de nuevo curso , Universidad de Minnesota (consultado el 25 de octubre de 2019)
- ^ Robin Cover (25 de febrero de 2002). "DSSSL - Lenguaje de especificación y semántica de estilo de documento. ISO / IEC 10179: 1996" . Páginas de portada . Consultado el 9 de agosto de 2012 .
- ^ " El lenguaje de secuencias de comandos principal para el GIMP que se le ha adjuntado hoy es Scheme " .Dov Grobgeld (2002). "Tutorial del esquema básico de GIMP" . El equipo de GIMP . Consultado el 9 de agosto de 2012 .
- ^ Todd Graham Lewis; David Zoll; Julian Missig (2002). "Preguntas frecuentes sobre GNOME de Internet Archive" . El equipo de Gnome, gnome.org. Archivado desde el original el 22 de mayo de 2000 . Consultado el 9 de agosto de 2012 .
- ^ "gnomo de astucia" . Fundación de Software Libre . Consultado el 9 de agosto de 2012 .
- ^ Laurence Brevard (9 de noviembre de 2006). " Actualización del programa Synopsys MAP-in SM : Foro de desarrolladores de interoperabilidad de EDA" (PDF) . Sinopsis Inc . Consultado el 9 de agosto de 2012 .
- ^ Kawai, Shiro (octubre de 2002). "Pegar las cosas juntas - esquema en la producción de contenido CG en tiempo real" . Actas de la Primera Conferencia Internacional Lisp, San Francisco : 342–348 . Consultado el 9 de agosto de 2012 .
- ^ Bill Magnuson; Hal Abelson y Mark Friedman (11 de agosto de 2009). "Bajo el capó de App Inventor para Android" . Google Inc, blog oficial de investigación de Google . Consultado el 9 de agosto de 2012 .
Otras lecturas
- Una introducción al esquema y su implementación ( un espejo )
- Christopher T. Haynes (22 de junio de 1999). "La experiencia de estandarización del lenguaje de programación del esquema" .
- Guy L. Steele Jr. , Richard P. Gabriel . "La evolución de Lisp" (PDF) .
- Gerald Sussman y Guy Steele , SCHEME: An Interpreter for Extended Lambda Calculus AI Memo 349 , Laboratorio de Inteligencia Artificial del MIT, Cambridge, Massachusetts, diciembre de 1975.
enlaces externos
- Esquema en Curlie
- Programación de esquemas en Wikilibros
- Escribe un plan en 48 horas en Wikilibros
- Medios relacionados con Scheme (lenguaje de programación) en Wikimedia Commons
- Bookmarklet que agrega REPL de esquema interactivo a cualquier sitio web