Esquema (lenguaje de programación)

Dialecto de Lisp
Esquema
ParadigmasMultiparadigma : funcional , imperativo , meta
FamiliaCeceo
Diseñado porGuy L. Steele
Gerald Jay Sussman
Apareció por primera vez1975 ; hace 49 años ( 1975 )
Versión estable
R7RS / 2013 ; hace 11 años ( 2013 )
Disciplina de mecanografíaDinámico , latente , fuerte.
AlcanceLéxico
Extensiones de nombre de archivo.scm, .ss
Sitio webwww.scheme.org
Implementaciones principales
Muchos
(ver Implementaciones de Scheme )
Influenciado por
ALGOL , Lisp , MDL
Influenciado
Clojure , Common Lisp , Dylan , EuLisp , Haskell , Hop , JavaScript , Julia , Lua , MultiLisp , Python , R , Racket , Ruby , Rust , [1] S , Scala , T
  • Esquema en Wikilibros

Scheme es un dialecto de la familia de lenguajes de programación Lisp . Scheme fue creado durante la década de 1970 en el Laboratorio de Ciencias de la Computación e Inteligencia Artificial del MIT (MIT CSAIL) y publicado 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 llamadas de cola , dando un soporte más fuerte para la programación funcional y técnicas asociadas como algoritmos recursivos. También fue uno de los primeros lenguajes de programación en soportar 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 estándar oficial del Instituto de Ingenieros Eléctricos y Electrónicos (IEEE) [3] y en un estándar de facto llamado Informe revisado sobre el lenguaje algorítmico Scheme (R n RS). Un estándar ampliamente implementado es el R5RS (1998). [4] El estándar de Scheme ratificado más recientemente es el "R7RS-small" (2013). [5] El R6RS, más expansivo y modular, fue ratificado en 2007. [6] Ambos descienden del R5RS; la cronología a continuación refleja el orden cronológico de ratificación.

Historia

Orígenes

Scheme comenzó en la década de 1970 como un intento de comprender el modelo de actores de Carl Hewitt , para lo cual Steele y Sussman escribieron un "pequeño intérprete de Lisp" usando Maclisp y luego "añadieron mecanismos para crear actores y enviar mensajes". [7] 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 seis caracteres cada uno como máximo. Actualmente, "Schemer" se usa comúnmente para referirse a un programador de Scheme.

R6RS

En el taller Scheme de 2003 se inició un nuevo proceso de estandarización del lenguaje, con el objetivo de producir un estándar R6RS en 2006. Este proceso rompió con el enfoque anterior de unanimidad de R n RS.

R6RS cuenta con 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 la R5.97RS. Una votación exitosa dio como resultado la ratificación del nuevo estándar, anunciado el 28 de agosto de 2007. [6]

Actualmente, las versiones más nuevas de varias implementaciones de Scheme [8] son ​​compatibles con el estándar R6RS. Existe una implementación de referencia portátil de las bibliotecas de fases implícitas propuestas para R6RS, llamada psyntax, que se carga y se inicia de manera adecuada en varias implementaciones de Scheme más antiguas. [9]

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 la disposición de la memoria. También calcula la máscara de bits del campo de objeto y las máscaras de bits del campo de objeto de Scheme mutables, y ayuda al recolector de basura a saber qué hacer con los campos sin 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 registros. [10]

R6RS introduce numerosos cambios significativos en el lenguaje. [11] El código fuente ahora se especifica en Unicode , y un gran subconjunto de caracteres Unicode ahora puede aparecer en símbolos e identificadores de Scheme , y hay otros cambios menores en las reglas léxicas. Los datos de caracteres también se especifican ahora en Unicode. Muchos procedimientos estándar se han trasladado a las nuevas bibliotecas estándar, que en sí mismas forman una gran expansión del estándar, que contiene procedimientos y formas sintácticas que anteriormente 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. Las reglas de sintaxis se han reemplazado por una función de abstracción sintáctica más expresiva (syntax-case) que permite el uso de todo Scheme en el momento de la expansión de macros. Ahora se requieren implementaciones compatibles para soportar la torre numérica completa de Scheme , y la semántica de los números se ha expandido, 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 algunos lo ven como un alejamiento de la filosofía minimalista. [12] [13] En agosto de 2009, el Comité Directivo de Scheme, que supervisa el proceso de estandarización, anunció su intención de recomendar dividir Scheme en dos lenguajes: un lenguaje de programación grande y moderno para programadores; y una versión pequeña, un subconjunto de la versión grande que conserva el minimalismo elogiado por los educadores e implementadores ocasionales. [14] Se crearon dos grupos de trabajo para trabajar en estas dos nuevas versiones de Scheme. El sitio Scheme Reports Process tiene enlaces a los estatutos de los grupos de trabajo, discusiones públicas y sistema de seguimiento de problemas.

El noveno borrador de R7RS (lenguaje reducido) se puso a disposición el 15 de abril de 2013. [15] La votación para ratificar este borrador se cerró el 20 de mayo de 2013, [16] y el informe final está disponible desde el 6 de agosto de 2013, describiendo "el lenguaje 'reducido' de ese esfuerzo: por lo tanto, no puede considerarse de manera aislada como el sucesor de R6RS". [5]

19581960196519701975198019851990199520002005201020152020
 LISP 1, 1.5, LISP 2 (abandonado)
 Maclisp
 Interlisp
 MDL
 Máquina Lisp Lisp
 Esquema R5RS R6RS R7RS pequeño
 NULO
 ZIL (lenguaje de implementación de Zork)
 Franz Lisp
 Ceceo común Norma ANSI
 El ceceo
 Esquema del MIT
 XLIP
 yo
 En Scheme
 Emacs Lisp
 AutoLISP
 PicoLisp
 Gambito
 EuLisp
 ISLISP
 OpenLisp
 Esquema PLT Raqueta
 nuevoLISP
 GNU Guile
 Visual LISP
 Clojure
 Arco
 LFE
 Hola
 Quialisp

Rasgos distintivos

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 s-expresions , listas entre paréntesis en las que un operador de prefijo es seguido por sus argumentos. Los programas Scheme, por lo tanto, consisten en secuencias de listas anidadas. Las listas también son la principal estructura de datos en Scheme, lo que lleva a una equivalencia cercana entre el código fuente y los formatos de datos ( homoiconicidad ). Los programas Scheme pueden crear y evaluar fácilmente fragmentos de código Scheme de forma dinámica.

La dependencia de las listas como estructuras de datos es compartida por todos los dialectos de Lisp. Scheme hereda un amplio conjunto de primitivas de procesamiento de listascons , como carycdr de sus progenitores de Lisp. Scheme utiliza variables tipificadas de forma estricta pero dinámica y admite procedimientos de primera clase . Por lo tanto, los procedimientos se pueden asignar como valores a variables o pasar como argumentos a procedimientos.

Esta sección se centra principalmente en las características innovadoras del lenguaje, incluidas aquellas que distinguen a Scheme de otros lenguajes Lisp. 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, se utiliza la notación "===> resultado" para indicar el resultado de evaluar la expresión en la línea inmediatamente anterior. Esta es la misma convención que se utiliza en R5RS.

Minimalismo

Scheme es un lenguaje muy simple, mucho más fácil de implementar que muchos otros lenguajes de poder expresivo comparable . [17] Esta facilidad es atribuible al uso del cálculo lambda para derivar gran parte de la sintaxis del lenguaje a partir de formas más primitivas. Por ejemplo, de las 23 construcciones sintácticas basadas en expresiones s definidas en el estándar Scheme R5RS, 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 (§3.1): "La más fundamental de las construcciones de enlace de variables es la expresión lambda, porque todas las demás construcciones de enlace de variables pueden explicarse en términos de expresiones lambda". [4]

Formas fundamentales : define, lambda, quote, if, define-sintaxis, let-sintaxis, letrec-sintaxis, reglas-sintaxis, set!
Formas derivadas : do, let, let*, letrec, cond, case, and, or, begin, named let, delay, unquote, unquote-splicing, quasiquote

Ejemplo: una macro para implementar letcomo expresión que se utiliza lambdapara realizar las vinculaciones de variables.

( define-sintaxis let ( reglas-sintaxis () (( let (( var expr ) ... ) cuerpo ... ) (( lambda ( var ... ) cuerpo ... ) expr ... ))))                

Por lo tanto, al utilizar letla definición anterior, 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 la implementación a la de codificar instancias de procedimientos.

En 1998, Sussman y Steele señalaron que el minimalismo de Scheme no era un objetivo de diseño consciente, sino más bien el resultado no deseado del proceso de diseño. "En realidad, 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 habíamos previsto... nos dimos cuenta de que el cálculo lambda (un formalismo pequeño y simple) podía servir como núcleo de un lenguaje de programación potente y expresivo". [7]

Ámbito léxico

Al igual que la mayoría de los lenguajes de programación modernos y a diferencia de los Lisp anteriores como Maclisp , Scheme tiene un alcance léxico: todas las posibles vinculaciones de variables 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 puede ser llamada. Esto contrasta con el alcance dinámico que era característico de los primeros dialectos de 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 los compiladores e intérpretes de la época. En esos Lisp, era perfectamente posible que una referencia a una variable libre dentro de un procedimiento hiciera referencia a vinculaciones bastante distintas externas al procedimiento, dependiendo del contexto de la llamada.

El impulso para incorporar el alcance léxico, que era un modelo de alcance inusual a principios de los años 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 lograr su objetivo inicial de implementar el modelo de actor de Hewitt en Lisp. [7]

Las ideas clave sobre cómo introducir el alcance léxico en un dialecto Lisp se popularizaron en el artículo Lambda de 1975 de Sussman y Steele, "Scheme: An Interpreter for Extended Lambda Calculus", [18] donde adoptaron el concepto de cierre léxico (en la página 21), que había sido descrito en un AI Memo en 1970 por Joel Moses , quien atribuyó la idea a Peter J. Landin . [19]

Cálculo lambda

La notación matemática de Alonzo Church , el cálculo lambda, ha inspirado el uso de "lambda" en Lisp como palabra clave para introducir un procedimiento, así como el desarrollo de técnicas de programación funcional que implican el uso de funciones de orden superior en Lisp. Pero los primeros Lisp no eran expresiones adecuadas del cálculo lambda debido a su tratamiento de las variables libres . [7]

Un sistema lambda formal tiene axiomas y una regla de cálculo completa. Es útil para el análisis utilizando lógica matemática y herramientas. 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 λ. [20] La función del cálculo lambda incluye: primero, servir como punto de partida de una lógica matemática poderosa. Segundo, puede reducir la necesidad 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. [21]

La introducción del alcance léxico resolvió el problema al hacer una equivalencia entre algunas formas de notación lambda y su expresión práctica en un lenguaje de programación funcional. Sussman y Steele demostraron que el nuevo lenguaje podía utilizarse para derivar de manera elegante toda la semántica imperativa y declarativa de otros lenguajes de programación, incluidos ALGOL y Fortran , y el alcance dinámico de otros lenguajes Lisp, utilizando expresiones lambda no como simples instancias de procedimientos sino como "estructuras de control y modificadores del entorno". [22] Introdujeron el estilo de paso de continuación junto con su primera descripción de Scheme en el primero de los Documentos Lambda, y en documentos posteriores, procedieron a demostrar el poder puro de este uso práctico del cálculo lambda.

Estructura de bloques

Scheme hereda su estructura de bloques de lenguajes estructurados en bloques anteriores, en particular ALGOL . En Scheme, los bloques se implementan mediante tres construcciones de enlace : let, let*y letrec. Por ejemplo, la siguiente construcción crea un bloque en el que un símbolo llamado varestá enlazado al número 10:

( define var "goose" ) ;; 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 de cualquier complejidad según las necesidades del programador. El uso de la estructuración de bloques para crear enlaces locales reduce el riesgo de colisión de espacios de nombres que, de lo contrario, puede ocurrir.

Una variante de let, let*, permite que los enlaces hagan referencia a variables definidas anteriormente en la misma construcción, de este modo:

( 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 procedimientos mutuamente recursivos se vinculen entre sí.

;; Cálculo de las secuencias masculina y femenina de Hofstadter como una lista de pares( define ( hofstadter-hombre-mujer n ) ( letrec (( mujer ( lambda ( n ) ( si ( = n 0 ) 1 ( - n ( hombre ( mujer ( - n 1 ))))))) ( hombre ( lambda ( n ) ( si ( = n 0 ) 0 ( - n ( mujer ( hombre ( - n 1 )))))))) ( let loop (( i 0 )) ( si ( > i n ) ' () ( cons ( cons ( mujer i ) ( hombre i )) ( loop ( + i 1 )))))))                                                   ( hofstadter-hombre-mujer 8 ) ===> (( 1 . 0 ) ( 1 . 0 ) ( 2 . 1 ) ( 2 . 2 ) ( 3 . 2 ) ( 3 . 3 ) ( 4 . 4 ) ( 5 . 4 ) ( 5 . 5 ) )                           

(Véase las secuencias masculina y femenina de Hofstadter para las definiciones utilizadas en este ejemplo).

Todos los procedimientos enlazados en un solo procedimiento letrecpueden referirse entre sí por su nombre, así como a valores de variables definidas anteriormente en el mismo procedimiento letrec, pero no pueden referirse a valores definidos posteriormente en el mismo procedimiento letrec.

Una variante de let, la forma "let con nombre", tiene un identificador después de la letpalabra 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 puede repetirse como se desee llamando al procedimiento. La forma 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, dopero es más idiomático en Scheme usar la recursión de cola para expresar la iteración . Se requieren implementaciones de Scheme que cumplan con los estándares para optimizar las llamadas de cola de modo de admitir una cantidad ilimitada 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 utilizando estructuras recursivas, que a veces son más intuitivas. Los procedimientos recursivos de cola y la forma nombradalet brindan soporte para la iteración utilizando la recursión de cola.

;; Creando una lista de cuadrados del 0 al 9: ;; Nota: loop es simplemente un símbolo arbitrario usado como etiqueta. Cualquier símbolo servirá.( define ( lista-de-cuadrados n ) ( deja bucle (( i n ) ( res ' ())) ( si ( < i 0 ) res ( bucle ( - 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 las instrucciones de retorno en lenguajes de programación imperativos. La siguiente función find-first, dadas function funcy list lst, devuelve el primer elemento xen lsttal que (func x)devuelva true.

( define ( find-first func lst ) ( call-with-current-continuation ( lambda ( return-immediately ) ( for-each ( lambda ( x ) ( if ( func x ) ( return-immediately x ))) lst ) #f )))                ( ¿ encontrar el primer entero? ' ( 1/2 3/4 5.6 7 8/9 10 11 )) ===> 7 ( ¿encontrar el primer 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 los 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, se muestra una secuencia de conteo:@*@**@***@****@*****@******@*******@********...

Espacio de nombres compartido para procedimientos y variables

A diferencia de Common Lisp, todos los datos y procedimientos de 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 requiere una notación especial para referirse a una función como valor. Esto a veces se conoce como la distinción " Lisp-1 vs. Lisp-2 ", que hace referencia al espacio de nombres unificado de Scheme y los espacios de nombres separados de Common Lisp. [23]

En Scheme, las mismas primitivas que se utilizan para manipular y vincular datos se pueden utilizar para vincular procedimientos. No existe un equivalente de defunlas #'primitivas de Common Lisp.

;; Variable ligada a un número: ( define f 10 ) f ===> 10 ;; Mutación (alteración del valor ligado) ( set! f ( + f f 6 )) f ===> 26 ;; Asignación de un procedimiento a la misma variable: ( set! f ( lambda ( n ) ( + n 12 ))) ( f 6 ) ===> 18 ;; Asignación del resultado de una expresión a la misma variable: ( set! f ( f 1 )) f ===> 13 ;; programación funcional: ( apply + ' ( 1 2 3 4 5 6 )) ===> 21 ( set! f ( lambda ( n ) ( + n 100 ))) ( map f ' ( 1 2 3 )) ===> ( 101 102 103 )                                          

Normas de implementación

Esta subsección documenta 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, incluidos los 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 en particular.

Los números pueden tener la cualidad de ser exactos. Un número exacto solo puede producirse mediante una secuencia de operaciones exactas que involucren 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 resulten en números exactos.

El estándar R5RS especifica los procedimientos exact->inexactque inexact->exactse pueden utilizar para cambiar la exactitud de un número. inexact->exactproduce "el número exacto que es numéricamente más cercano al argumento". exact->inexactproduce "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 exige que las implementaciones de Scheme implementen toda la torre numérica, pero deben implementar "un subconjunto coherente que sea 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 sí exige 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... de modo que siempre devuelvan resultados exactos cuando se les den argumentos exactos" (R6RS sec. 3.4, sec. 11.7.1). [6]

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 ( defina 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: La misma aritmética en una implementación que no admite números racionales exactos ni números complejos, pero sí acepta números reales en notación racional.

;; Suma de cuatro números reales racionales ( defina xr ( + 1/3 1/4 -1/5 405/50 )) ;; Suma de dos números reales racionales ( defina xi ( + -1/3 2/3 )) xr ===> 8.48333333333333 xi ===> 0.333333333333333 ;; Verifique la exactitud. ( ¿exacto? xr ) ===> #f ( ¿exacto? xi ) ===> #f                

Ambas implementaciones cumplen con el estándar R5RS pero la segunda no cumple con el R6RS porque no implementa la torre numérica completa.

Evaluación retrasada

El esquema apoya la evaluación diferida a través del delayformulario y el procedimiento force.

( define un 10 ) ( define eval-aplus2 ( delay ( + a 2 ))) ( establece! a 20 ) ( fuerza eval-aplus2 ) ===> 22 ( define eval-aplus50 ( delay ( + a 50 ))) ( deja (( a 8 )) ( fuerza eval-aplus50 )) ===> 70 ( establece! a 100 ) ( fuerza eval-aplus2 ) ===> 22                         

Se conserva el contexto léxico de la definición original de la promesa 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 streams . [24]

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 sugiere una implementación de delayy force, implementando la promesa como un procedimiento sin argumentos (un thunk ) y usando memorización para garantizar que solo se evalúe una vez, independientemente de la cantidad de veces forceque 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 utilizando las funciones definidas en SRFI 41: [24]

;; Define la secuencia de Fibonacci: ( define fibs ( stream-cons 0 ( stream-cons 1 ( stream-map + fibs ( stream-cdr fibs ))))) ;; Calcula el número centésimo en la secuencia: ( stream-ref fibs 99 ) ===> 218922995834555169026             

Orden de evaluación de los argumentos de procedimiento

La mayoría de los lenguajes Lisp especifican un orden de evaluación para los argumentos de los procedimientos. Scheme no lo hace. El orden de evaluación (incluido el orden en el que se evalúa la expresión en la posición del operador) puede ser elegido por una implementación en cada llamada, y la única restricción es que "el efecto de cualquier evaluación concurrente de las expresiones de operador y operando está restringido a ser consistente con algún orden secuencial de evaluación". (R5RS sec. 4.1.3) [4]

( let (( ev ( lambda ( n ) ( display "Evaluando " ) ( display ( if ( procedimiento? n ) "procedimiento" n )) ( newline ) n ))) (( ev + ) ( ev 1 ) ( ev 2 ))) ===> 3                   
Evaluación 1 Evaluación 2 Procedimiento de evaluación

ev es un procedimiento que describe el argumento que se le pasa y luego devuelve el valor del argumento. A diferencia de otros Lisp, la aparición de una expresión en la posición del operador (el primer elemento) de una expresión de Scheme es completamente legal, siempre que el resultado de la expresión en la posición del operador sea un procedimiento.

Al llamar al procedimiento " + " para sumar 1 y 2, las expresiones (ev+), (ev1) y (ev2) pueden evaluarse en cualquier orden, siempre que el efecto no sea como si se evaluaran en paralelo. Por lo tanto, las siguientes tres líneas pueden mostrarse en cualquier orden mediante Scheme estándar cuando se ejecuta el código de ejemplo anterior, aunque el texto de una línea no puede intercalarse con el de otra porque eso violaría la restricción de evaluación secuencial.

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 potente sistema de macros higiénico que permite al programador añadir nuevas construcciones sintácticas al lenguaje utilizando un sublenguaje de coincidencia de patrones simple (R5RS sec 4.3). [4] Antes de esto, el sistema de macros higiénico había sido relegado a un apéndice del estándar R4RS, como un sistema de "alto nivel" junto con un sistema de macros de "bajo nivel", ambos tratados como extensiones de Scheme en lugar de una parte esencial del lenguaje. [25]

Las implementaciones del sistema de macros higiénico, también llamado syntax-rules, deben respetar el alcance léxico del resto del lenguaje. Esto se garantiza mediante reglas especiales de denominación 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-caseque ha estado disponible como una extensión del lenguaje de R5RS Scheme durante algún tiempo.

;; Define una macro para implementar una variante de "si" con una multiexpresión ;; rama verdadera y ninguna rama falsa. ( define-syntax when ( syntax-rules () (( when pred exp exps ... ) ( if pred ( begin exp exps ... )))))              

Las invocaciones de macros y procedimientos tienen un gran parecido (ambas son expresiones s), pero se tratan de forma diferente. Cuando el compilador encuentra una expresión s en el programa, primero comprueba 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 queden invocaciones de macros. 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 en la cabecera de la expresión s y llamarla como un procedimiento con las expresiones de cola evaluadas pasadas como argumentos.

La mayoría de las implementaciones de Scheme también proporcionan sistemas de macros adicionales. Entre los más populares se encuentran los cierres sintácticos , el cambio de nombre explícito de macros y define-macroun sistema de macros no higiénico similar al defmacrosistema proporcionado en Common Lisp .

La imposibilidad de especificar si una macro es higiénica o no es una de las deficiencias del sistema macro. Los modelos alternativos de expansión, como los conjuntos de alcance, ofrecen una posible solución. [26]

Entornos y evaluación

Antes de R5RS, Scheme no tenía un equivalente estándar del evalprocedimiento que es omnipresente en otros Lisp, aunque el primer documento de Lambda lo había descrito evaluatecomo "similar a la función EVAL de LISP" [18] y el primer informe revisado en 1978 lo reemplazó por enclose, que tomaba dos argumentos. El segundo, tercer y cuarto informes 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: [27]

( let (( nombre '+ )) ( let (( + * )) ( evaluar ( lista nombre 2 3 ))))          

Si se evalúa en el entorno externo, donde namese define , el resultado es la suma de los operandos. Si se evalúa en el entorno interno, donde se ha asociado el símbolo "+" 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 evalque toma una expresión s y un entorno y evalúa la expresión en el entorno proporcionado. (R5RS sec. 6.5) [4] R6RS extiende esto proporcionando un procedimiento llamado environmentpor 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 evaluateque puede verse así:

( define ( evalúa expr ) ( eval expr ( entorno de interacción )))     

interaction-environmentes 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 NILse evalúa como el valor falso en una expresión booleana. En Scheme, desde la norma IEEE de 1991, [3] todos los valores excepto #f, incluido NILel equivalente de en Scheme que se escribe como '(), se evalúan como el valor verdadero en una expresión booleana. (R5RS sec. 6.3.1) [4]

Mientras que la constante que representa el valor booleano de verdadero es Ten la mayoría de los Lisp, en Scheme es #t.

Disyunción de tipos de datos primitivos

En Scheme, los tipos de datos primitivos son disjuntos. Solo uno de los siguientes predicados puede ser verdadero para cualquier objeto de Scheme: boolean?, pair?, symbol?, number?, char?, string?, vector?, port?, procedure?. (R5RS sec 3.2) [4]

En cambio, dentro del tipo de datos numéricos, los valores numéricos se superponen. Por ejemplo, un valor entero satisface todos los predicados integer?, rational?, real?y al mismo tiempo. (R5RS sec 6.2) complex?[ 4]number?

Predicados de equivalencia

El esquema 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 #fmenos que sus parámetros representen el mismo objeto de datos en la memoria;
  • eqv?es generalmente lo mismo que eq?pero trata los objetos primitivos (por ejemplo, caracteres y números) de manera especial, de modo que los números que representan el mismo valor son eqv?pares si no se refieren al mismo objeto;
  • equal?Compara estructuras de datos como listas, vectores y cadenas para determinar si tienen estructura y eqv?contenidos congruentes. (R5RS sec. 6.1) [4]

En Scheme también existen operaciones de equivalencia dependientes de tipo: string=?y string-ci=?compara dos cadenas (la última realiza una comparación independiente de mayúsculas y minúsculas); char=?y char-ci=?compara caracteres; =compara números. [4]

Comentarios

Hasta el estándar R5RS, el comentario estándar en Scheme era un punto y coma, 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 sola línea, y el estándar R6RS permite dos de ellas: una expresión s completa se puede convertir en un comentario (o "comentarla") al anteponerla con #;(introducido en SRFI 62 [28] ) y se puede producir un comentario de varias líneas o "comentario en bloque" al rodear el texto con #|y |#.

Entrada/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-porty current-output-port, que corresponden a las nociones 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 está soportada en el estándar, por procedimientos estándar como with-input-from-filey with-output-to-file. La mayoría de las implementaciones proporcionan puertos de cadena con capacidades de redirección similares, lo que permite que muchas operaciones normales de entrada-salida se realicen en búferes de cadena en lugar de archivos, utilizando procedimientos descritos en SRFI 6. [29] 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 el estricto esquema R5RS.

Ejemplo 1: Con salida predeterminada a (puerto de salida actual):

( let (( hola0 ( lambda () ( display "Hola mundo" ) ( nueva línea )))) ( hola0 ))      

Ejemplo 2: Como 1, pero usando el 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 el archivo explícito abierto y el puerto cerrado para enviar la salida al archivo

( let (( hola1 ( lambda ( p ) ( display "Hola mundo" p ) ( newline p ))) ( puerto-de-salida ( abrir-archivo-de-salida "archivo-de-salida-holamundo" ))) ( hola1 puerto-de-salida ) ( cerrar-puerto-de-salida puerto -de-salida ))               

Ejemplo 5: Como 2, pero usando call-with-output-file para enviar la salida a un archivo.

( let (( hola1 ( lambda ( p ) ( display "Hola mundo" p ) ( nueva línea p )))) ( llamada-con-archivo-de-salida "archivo-de-salida-holamundo" hola1 ))           

Se proporcionan procedimientos similares para la entrada. R5RS Scheme proporciona los predicados input-port?y output-port?. Para la entrada y salida de caracteres, write-charse proporcionan read-char, peek-chary . Para escribir y leer expresiones de Scheme, Scheme proporciona y . 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 utilizando el predicado .char-ready?readwriteeof-object?

Con el estándar SRFI 28 también se define un procedimiento de formato básico similar a formatla función de Common Lisp, que le da nombre. [30]

Redefinición de procedimientos estándar

En Scheme, los procedimientos están vinculados a variables. En R5RS, el estándar de lenguaje exigió formalmente que los programas pudieran cambiar las vinculaciones de variables de los procedimientos integrados, redefiniéndolos de manera efectiva. (R5RS "Cambios de lenguaje") [4] Por ejemplo, +se puede ampliar para aceptar cadenas y números redefiniéndolo:

( ¡establecer! + ( dejar (( original+ + )) ( lambda argumentos ( aplicar ( si ( o ( nulo? argumentos ) ( cadena? ( auto argumentos ))) cadena-agregar original+ ) argumentos )))) ( + 1 2 3 ) ===> 6 ( + "1" "2" "3" ) ===> "123"                         

En R6RS, cada enlace, incluidos los estándar, pertenece a alguna biblioteca y todos los enlaces exportados son inmutables. (R6RS sec 7.1) [6] Debido a esto, la redefinición de procedimientos estándar por mutación está prohibida. En cambio, es posible importar un procedimiento diferente bajo el nombre de uno estándar, lo que en efecto es similar a la redefinición.

Nomenclatura y convenciones de nombres

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 datos ya asignados terminan con un "!". Los programadores de Scheme suelen seguir estas convenciones.

En contextos formales como los estándares de Scheme, se utiliza la palabra "procedimiento" en lugar de "función" para referirse a una expresión lambda o un procedimiento primitivo. En el uso normal, las palabras "procedimiento" y "función" se utilizan indistintamente. A veces, la aplicación de un procedimiento se denomina formalmente combinación .

Al igual que en otros Lisp, el término " thunk " se utiliza en Scheme para referirse a un procedimiento sin argumentos. El término "recursión de cola adecuada" se refiere a la propiedad de todas las implementaciones de Scheme de que realizan una optimización de llamadas de cola para admitir una cantidad indefinida de llamadas de cola activas .

La forma de los títulos de los documentos de estándares desde R3RS, "Informe 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 está estrechamente modelada en la página Resumen del Informe ALGOL 60. [31] [32]

Revisión de formularios y procedimientos estándar

El lenguaje está definido formalmente en los estándares R5RS (1998) [4] y R6RS (2007) [6] . En ellos se describen "formas" estándar: palabras clave y sintaxis que las acompañan, que proporcionan la estructura de control del lenguaje, y procedimientos estándar que realizan tareas comunes.

Formularios estándar

En esta tabla se describen los formatos estándar de Scheme. Algunos formatos aparecen en más de una fila porque no se pueden clasificar fácilmente en una única función del lenguaje.

Las formas marcadas con una "L" en esta tabla se clasifican como formas de "biblioteca" derivadas en el estándar y a menudo se implementan como macros utilizando formas 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.

Formas estándar en el lenguaje Esquema R5RS
ObjetivoFormularios
Definicióndefinir
Construcciones vinculanteslambda, hacer (L), dejar (L), dejar* (L), letrec (L)
Evaluación condicionalsi, cond (L), caso (L), y (L), o (L)
Evaluación secuencialcomenzar (*)
Iteraciónlambda, hacer (L), llamado dejar (L)
Extensión sintácticadefine-sintaxis, let-sintaxis, letrec-sintaxis, reglas-sintaxis (R5RS), sintaxis-case (R6RS)
Citandoquote('), unquote(,), quasiquote(`), unquote-splicing(,@)
Asignación¡colocar!
Evaluación retrasadaretraso (L)

Si bien beginse define como una sintaxis de biblioteca en R5RS, el expansor debe conocerla para lograr la función de empalme. En R6RS ya no es una sintaxis de biblioteca.

Procedimientos estándar

Las dos tablas siguientes describen los procedimientos estándar del esquema R5RS. El esquema 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 pueden clasificarse fácilmente en una sola función en el lenguaje.

Procedimientos estándar en el lenguaje R5RS Scheme
ObjetivoProcedimientos
Construcciónvector, crear-vector, crear-cadena, lista
Predicados de equivalenciaeq?, eqv?, igual?, cadena=?, cadena-ci=?, char=?, char-ci=?
Conversión de tiposvector->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úmerosVer tabla aparte
Instrumentos de cuerdacadena?, crear-cadena, cadena, longitud-de-cadena, referencia-de-cadena, ¡conjunto-de-cadena!, cadena=?, cadena-ci=?, cadena<? cadena-ci<?, cadena<=? cadena-ci<=?, cadena>? cadena-ci>?, cadena>=? cadena-ci>=?, subcadena, cadena-añadida, cadena->lista, lista->cadena, cadena-copia, cadena-rellenada!
Personajeschar?, char=?, char-ci=?, char<? char-ci<?, char<=? char-ci<=?, char>? char-ci>?, char>=? char-ci>=?, char-alfabético?, char-numérico?, char-espacio?, char-mayúscula?, char-minúscula?, char->entero, entero->char, char-mayúscula, char-minúscula
Vectores¡crear-vector, vector, vector?, longitud-vector, referencia-vector, conjunto-vector!, vector->lista, lista->vector, ¡relleno-vector!
Símbolossímbolo->cadena, cadena->símbolo, ¿símbolo?
Pares y listaspar?, contras, auto, cdr, ¡establecer auto!, ¡establecer cdr!, ¿nulo?, ¿lista?, lista, longitud, anexar, revertir, cola de lista, referencia de lista, 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?
Continuacionesllamada con continuación actual (call/cc), valores, llamada con valores, viento dinámico
Entornoseval, entorno de informe de esquema, entorno nulo, entorno de interacción (opcional)
Entrada/salidamostrar, nueva línea, leer, escribir, leer-carácter, escribir-carácter, ver-carácter, ¿carácter-listo?, ¿fin-de-objeto? abrir-archivo-de-entrada, abrir-archivo-de-salida, cerrar-puerto-de-entrada, cerrar-puerto-de-salida, ¿puerto-de-entrada?, ¿puerto-de-salida?, puerto-de-entrada-actual, puerto-de-salida-actual, llamada-con-archivo-de-entrada, llamada-con-archivo-de-salida, con-entrada-desde-archivo(opcional), con-salida-a-archivo(opcional)
Interfaz del sistemacargar (opcional), transcripción activada (opcional), transcripción desactivada (opcional)
Evaluación retrasadafuerza
Programación funcionalprocedimiento?, aplicar, mapa, para cada uno
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.

Procedimientos numéricos estándar en el lenguaje R5RS Scheme
ObjetivoProcedimientos
Operadores aritméticos básicos+, -, *, /, abs, cociente, resto, módulo, mcd, mcm, expt, sqrt
Números racionalesnumerador, denominador, racional?, racionalizar
Aproximaciónpiso, techo, truncado, redondo
Exactitudinexacto->exacto, exacto->inexacto, ¿exacto?, ¿inexacto?
Desigualdades<, <=, >, >=, =
Predicados varios¿cero?, ¿negativo?, ¿positivo?, ¿impar?, ¿par?
Máximo y mínimomáximo, mínimo
Trigonometríapecado, cos, bronceado, asin, acos, atan
Exponencialesexp, registro
Números complejoshacer-rectangular, hacer-polar, parte-real, parte-imag, magnitud, ángulo, ¿complejo?
Entrada-salidanú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 implementación del plan

Debido al minimalismo de Scheme, muchos procedimientos y formas sintácticas comunes no están definidos por el estándar. Para mantener el lenguaje básico pequeño pero facilitar la estandarización de extensiones, la comunidad de Scheme tiene un proceso de "Solicitud de implementación de Scheme" (SRFI, por sus siglas en inglés) mediante el cual se definen bibliotecas de extensión a través de un análisis cuidadoso 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: [33]

  • 0: construcción de expansión condicional basada en características
  • 1: lista de bibliotecas
  • 4: tipos de datos vectoriales numéricos homogéneos
  • 6: puertos de cadena básicos
  • 8: recibir, vinculación a múltiples valores
  • 9: definición de tipos de registros
  • 13: biblioteca de cadenas
  • 14: biblioteca de conjuntos de caracteres
  • 16: sintaxis para procedimientos de aridad variable
  • 17: ¡conjunto generalizado!
  • 18: Compatibilidad con subprocesos múltiples
  • 19: tipos de datos de tiempo y procedimientos
  • 25: primitivas de matrices multidimensionales
  • 26: notación para especializar parámetros sin currificar
  • 27: fuentes de bits aleatorios
  • 28: cadenas de formato básicas
  • 29: localización
  • 30: comentarios anidados de varias líneas
  • 31: una forma especial para la evaluación recursiva
  • 37: args-fold: un procesador de argumentos del programa
  • 39: objetos de parámetros
  • 41: arroyos
  • 42: comprensiones ansiosas
  • 43: biblioteca de vectores
  • 45: primitivas para expresar algoritmos iterativos perezosos
  • 60: números enteros como bits
  • 61: una cláusula condicional más general
  • 66: vectores de octetos
  • 67: comparar procedimientos

Implementaciones

El diseño elegante y minimalista ha hecho de Scheme un objetivo popular para diseñadores de lenguajes, 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 scripting . Esto ha dado lugar a decenas de implementaciones, [34] la mayoría de las cuales difieren entre sí tanto que trasladar programas de una implementación a otra es bastante difícil, y el pequeño tamaño del lenguaje estándar significa que escribir un programa útil de gran complejidad en Scheme estándar y portable es casi imposible. [14] 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 de lectura-evaluación-impresión al estilo Lisp tradicional para el desarrollo y la depuración. Muchas también compilan programas Scheme en binario ejecutable. El soporte para incrustar código Scheme en programas escritos en otros lenguajes también es común, ya que la relativa simplicidad de las implementaciones de Scheme lo convierte en una opción popular para agregar capacidades de scripting a sistemas más grandes desarrollados en lenguajes como C. Los intérpretes de Scheme Gambit , Chicken y Bigloo compilan Scheme en C, lo que hace que la incrustación sea mucho más sencilla. Además, el compilador de Bigloo se puede configurar para generar código de bytes para la máquina virtual Java (JVM) y tiene 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 Java , y los compiladores de Scheme a C suelen facilitar el uso de bibliotecas externas escritas en C, hasta el punto de permitir la incorporación de código C en el código fuente de Scheme. Otro ejemplo es Pvts, que ofrece un conjunto de herramientas visuales que respaldan el aprendizaje de Scheme.

Uso

Scheme es ampliamente utilizado por varias [35] escuelas; en particular, varios cursos introductorios de informática utilizan Scheme junto con el libro de texto Structure and Interpretation of Computer Programs (SICP). [36] Durante los últimos 12 años, PLT ha llevado a cabo 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. La antigua clase introductoria de programación 6.001 del MIT se enseñaba en Scheme, [37] Aunque 6.001 ha sido reemplazado por cursos más modernos, SICP continúa enseñándose en el MIT. [38] Del mismo modo, la clase introductoria en UC Berkeley , CS 61A, se enseñó hasta 2011 completamente en Scheme, salvo pequeñas desviaciones hacia 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 currículo antiguo y partes de la clase todavía se enseñan en Scheme. [39]

El libro de texto How to Design Programs de Matthias Felleisen, actualmente en la Northeastern University, es utilizado por algunos institutos de educación superior para sus cursos introductorios de informática. Tanto la Northeastern University como el Worcester Polytechnic Institute utilizan Scheme exclusivamente para sus cursos introductorios Fundamentals of Computer Science (CS2500) e Introduction to Program Design (CS1101), respectivamente. [40] [41] Rose-Hulman utiliza Scheme en su curso más avanzado Programming Language Concepts. [42] El curso principal de Brandeis University , Structure and Interpretations of Computer Programs (COSI121b), también se enseña exclusivamente en Scheme por el científico informático teórico Harry Mairson . [43] La clase introductoria de Indiana University , C211, se enseña completamente en Scheme. Una versión a tu propio ritmo del curso, CS 61AS, continúa utilizando Scheme. [44] Los cursos introductorios de informática en Yale y Grinnell College también se enseñan en Scheme. [45] Paradigmas de diseño de programación, [46] un curso obligatorio para los estudiantes de posgrado en informática de la Universidad Northeastern , también utiliza ampliamente Scheme. El antiguo curso introductorio de informática de la Universidad de Minnesota - Twin Cities, CSCI 1901, también utilizó Scheme como su lenguaje principal, seguido de un curso que introdujo a los estudiantes al lenguaje Java; [47] sin embargo, siguiendo el ejemplo del MIT, el departamento reemplazó 1901 con el CSCI 1133 basado en Python, [48] mientras que la programación funcional se cubre en detalle en el curso de tercer semestre CSCI 2041. [49]

El esquema también se utilizó para lo siguiente:

Véase también

Referencias

  1. ^ "Influencias - La referencia de Rust". La referencia de Rust . Consultado el 18 de abril de 2023 .
  2. ^ Common LISP: The Language, 2.ª edición, 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, en cierta medida, por Scheme e InterLisp". 
  3. ^ ab 1178-1990 (Reaff 2008) Estándar IEEE para el lenguaje de programación Scheme. Número de parte IEEE STDPD14209, reafirmado por unanimidad en una reunión del Comité de Revisión de Estándares (RevCom) del Consejo de Estándares IEEE-SA, 26 de marzo de 2008 (ítem 6.3 sobre las actas), actas de reafirmación consultadas en octubre de 2009. Este documento está disponible en IEEE solo para su compra y no está en línea al momento de redactarse: 2009.
  4. ^ abcdefghijklmnopqr Richard Kelsey; William Clinger; Jonathan Rees; et al. (agosto de 1998). "Informe revisado5 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 .
  5. ^ ab "R7RS final disponible" (PDF) . 2013-07-06.
  6. ^ abcde Sperber, Michael; Dybvig, R. Kent; Flatt, Matthew; Van Straaten, Anton; et al. (agosto de 2007). "Informe revisado6 sobre el esquema de lenguaje algorítmico (R6RS)". Comité directivo del esquema . Consultado el 13 de septiembre de 2011 .
  7. ^ abcd Sussman, Gerald Jay; Steele, Guy L. (1 de diciembre de 1998). "El primer informe sobre Scheme revisitado". Computación simbólica y de orden superior . 11 (4): 399–404. doi :10.1023/A:1010079421970. S2CID  7704398.
  8. ^ "Implementaciones de R6RS". r6rs.org . Consultado el 24 de noviembre de 2017 .
  9. ^ Abdulaziz Ghuloum (27 de octubre de 2007). "Bibliotecas R6RS y sistema de sintaxis y casos (psyntax)". Esquema de Ikarus . Consultado el 20 de octubre de 2009 .
  10. ^ Keep, Andrew W.; Dybvig, R. Kent (noviembre de 2014). "Una representación en tiempo de ejecución de tipos de registros de esquema". Journal of Functional Programming . 24 (6): 675–716. doi : 10.1017/S0956796814000203 . S2CID  40001845.
  11. ^ "Informe revisado^6 sobre el esquema de lenguaje algorítmico, Apéndice E: cambios en el lenguaje". Comité Directivo del Esquema. 2007-09-26 . Consultado el 2009-10-20 .
  12. ^ "Electorado R6RS". Comité Directivo del Plan. 2007. Consultado el 9 de agosto de 2012 .
  13. ^ Marc Feeley (compilación) (26 de octubre de 2007). "Intenciones de los implementadores en relación con R6RS". Comité directivo del proyecto, lista de correo r6rs-discuss . Consultado el 9 de agosto de 2012 .
  14. ^ ab Will Clinger, Marc Feeley, Chris Hanson, Jonathan Rees y Olin Shivers (2009-08-20). "Declaración de posición (borrador)". Comité Directivo del Plan . Consultado el 2012-08-09 .{{cite web}}: CS1 maint: varios nombres: lista de autores ( enlace )
  15. ^ "El noveno borrador del R7RS está disponible" (PDF) . 2013-04-15.
  16. ^ Will Clinger (10 de mayo de 2013). "extensión del período de votación". Comité Directivo del Lenguaje del Esquema, lista de correo de informes del esquema. Archivado desde el original el 21 de julio de 2013. Consultado el 7 de julio de 2013 .
  17. ^ La implementación de Scheme 48 se llama así porque el intérprete fue escrito por Richard Kelsey y Jonathan Rees en 48 horas (6 y 7 de agosto de 1986). Consulte Richard Kelsey; Jonathan Rees; Mike Sperber (10 de enero de 2008). "El manual de referencia incompleto de Scheme 48 para la versión 1.8". Jonathan Rees, s48.org . Consultado el 9 de agosto de 2012 .
  18. ^ de Gerald Jay Sussman y Guy Lewis Steele Jr. (diciembre de 1975). "Scheme: An Interpreter for Extended Lambda Calculus" (PDF) . AI Memos . AIM-349. MIT AI Lab . hdl :1721.1/5794 . Consultado el 23 de diciembre de 2021 .
  19. ^ 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 pensar en QUOTE como una cubierta porosa o abierta de la función ya que las variables libres escapan al entorno actual. FUNCTION actúa como una cubierta cerrada o no porosa (de ahí el término "cierre" utilizado por Landin). Por lo tanto, hablamos de expresiones Lambda "abiertas" (las funciones en LISP son generalmente expresiones Lambda) y expresiones Lambda "cerradas". [...] Mi interés en el problema del entorno 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 .
  20. ^ van Tonder, André (1 de enero de 2004). "Un cálculo Lambda para computación cuántica". Revista SIAM de Computación . 33 (5): 1109–1135. arXiv : quant-ph/0307150 . doi :10.1137/S0097539703432165. S2CID  613571.
  21. ^ Niehren, J.; Schwinghammer, J.; Smolka, G. (noviembre de 2006). "Un cálculo lambda concurrente con futuros" (PDF) . Theoretical Computer Science . 364 (3): 338–356. doi :10.1016/j.tcs.2006.08.016.
  22. ^ Gerald Jay Sussman y Guy Lewis Steele Jr. (marzo de 1976). "Lambda: el imperativo definitivo". AI Memos . AIM-353. MIT AI Lab . Archivado desde el original (posdata o PDF) el 2016-05-10 . Consultado el 2012-08-09 .
  23. ^ Gabriel, Richard P. ; Pitman, Kent (1988). "Cuestiones técnicas de separación en celdas de función y celdas de valor". LISP and Symbolic Computation . Vol. 1, no. 1 (publicado en junio de 1988). págs. 81–101. doi :10.1007/BF01806178 . Consultado el 9 de agosto de 2012 .
  24. ^ por Philip L. Bewig (24 de enero de 2008). "SRFI 41: Streams". Los editores de SRFI, schemers.org . Consultado el 9 de agosto de 2012 .
  25. ^ William Clinger y Jonathan Rees, ed. (1991). "Informe revisado4 sobre el esquema de lenguaje algorítmico". ACM Lisp Pointers . 4 (3): 1–55 . Consultado el 9 de agosto de 2012 .
  26. ^ Flatt, Matthew (2016). "Enlace como conjuntos de ámbitos". 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. Número de identificación del sujeto  15401805.
  27. ^ Jonathan Rees, The Scheme of Things The June 1992 Meeting Archivado el 16 de julio de 2011 en Wayback Machine (posdata), en Lisp Pointers, V(4), octubre-diciembre de 1992. Consultado el 9 de agosto de 2012.
  28. ^ Taylor Campbell (21 de julio de 2005). «SRFI 62: comentarios sobre la expresión S». Los editores de SRFI, schemers.org . Consultado el 9 de agosto de 2012 .
  29. ^ William D Clinger (1 de julio de 1999). "SRFI 6: puertos de cadenas básicos". Los editores de SRFI, schemers.org . Consultado el 9 de agosto de 2012 .
  30. ^ Scott G. Miller (25 de junio de 2002). "SRFI 28: Cadenas de formato básicas". Los editores de SRFI, schemers.org . Consultado el 9 de agosto de 2012 .
  31. ^ 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, Communications of the ACM y Journal of the British Computer Society . Consultado el 9 de agosto de 2012 .
  32. ^ 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 SIGPLAN de la ACM . 21 (12): 37–79. CiteSeerX 10.1.1.29.3015 . doi :10.1145/15042.15043. hdl :1721.1/6424. S2CID  43884422 . Consultado el 9 de agosto de 2012 . 
  33. ^ "Sistemas de esquemas que respaldan a las instituciones financieras de inversión socialmente responsable". Los editores de las instituciones financieras de inversión socialmente responsable, schemers.org. 2009-08-30 . Consultado el 2012-08-09 .
  34. ^ Se enumeran 75 implementaciones conocidas de Scheme en "scheme-faq-standards". Wiki de Scheme de la comunidad. 25 de junio de 2009. Consultado el 20 de octubre de 2009 .
  35. ^ Ed Martin (20 de julio de 2009). "Lista de escuelas que utilizan Scheme". Schemers Inc. Consultado el 20 de octubre de 2009 .
  36. ^ "Lista de escuelas que utilizan el SICP". MIT Press. 26 de enero de 1999. Consultado el 20 de octubre de 2009 .
  37. ^ Eric Grimson (primavera de 2005). «6.001 Estructura e interpretación de programas informáticos». MIT Open Courseware . Consultado el 20 de octubre de 2009 .
  38. ^ Alex Vandiver; Nelson Elhage; et al. (Enero de 2009). "6.184 - Los zombis beben con cafeína 6.001". MIT CSAIL . Consultado el 20 de octubre de 2009 .
  39. ^ John DeNero (otoño de 2019). «Computer Science 61A, Berkeley». Departamento de Ingeniería Eléctrica y Ciencias de la Computación, Berkeley . Consultado el 17 de diciembre de 2019 .
  40. ^ CS 2500: Fundamentos de informática I, Northeastern University
  41. ^ CS 1101: Introducción al diseño de programas (A05): software del curso, Worcester Polytechnic Institute
  42. ^ "CSSE 304: Conceptos de lenguaje de programación". Instituto Tecnológico Rose-Hulman .
  43. ^ "Programa de estudios CS121b primavera 2021" (PDF) . Universidad Brandeis .
  44. ^ "Inicio". berkeley-cs61as.github.io .
  45. ^ Dana Angluin (otoño de 2009). "Introducción a la informática (CPSC 201)". The Zoo, Departamento de informática de la Universidad de Yale . Consultado el 20 de octubre de 2009 .
  46. ^ "Lecturas del curso CSG107 de Paradigmas de diseño de programación". Facultad de informática y ciencias de la información de la Universidad Northeastern. Otoño de 2009. Consultado el 9 de agosto de 2012 .
  47. ^ Estructura de la programación informática I Archivado el 19 de junio de 2010 en Wayback Machine , Departamento de Ciencias de la Computación, Universidad de Minnesota, primavera de 2010 (consultado el 30 de enero de 2010).
  48. ^ Descripciones de los cursos obligatorios de CSci y otra información Archivado 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)
  49. ^ CSCI 2041—Nuevo curso Comité de currículo de CSE, Universidad de Minnesota (consultado el 25 de octubre de 2019)
  50. ^ Robin Cover (25 de febrero de 2002). "DSSSL - Document Style Semantics and Specification Language. ISO/IEC 10179:1996". Portadas . Consultado el 9 de agosto de 2012 .
  51. ^ " El principal lenguaje de programación para GIMP que se le ha asociado hasta el momento es Scheme ". De Dov Grobgeld (2002). "El tutorial básico de Scheme para GIMP". El equipo de GIMP . Consultado el 9 de agosto de 2012 .
  52. ^ Todd Graham Lewis; David Zoll; Julian Missig (2002). "GNOME FAQ from 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 .
  53. ^ "guile-gnome". Free Software Foundation . Consultado el 9 de agosto de 2012 .
  54. ^ Laurence Brevard (9 de noviembre de 2006). "Actualización del programa Synopsys MAP-inSM: Foro de desarrolladores de interoperabilidad EDA" (PDF) . Synopsis Inc. Consultado el 9 de agosto de 2012 .
  55. ^ Kawai, Shiro (octubre de 2002). "Gluing Things Together - Scheme in the Real-time CG Content Production". Actas de la Primera Conferencia Internacional de Lisp, San Francisco : 342–348 . Consultado el 9 de agosto de 2012 .
  56. ^ Bill Magnuson; Hal Abelson y Mark Friedman (11 de agosto de 2009). "Under the Hood of App Inventor for Android". Google Inc, blog oficial de Google Research . Consultado el 9 de agosto de 2012 .

Lectura adicional

  • scheme.org proporciona enlaces a muchos recursos de Scheme, incluidas las especificaciones
  • Programación Scheme en Wikilibros
  • Introducción al esquema
  • Escribe tu propio esquema en 48 horas en Wikilibros
  • Medios relacionados con Scheme (lenguaje de programación) en Wikimedia Commons
  • Esquema semanal
  • Bookmarklet que agrega Interactive Scheme REPL a cualquier sitio web
Obtenido de "https://es.wikipedia.org/w/index.php?title=Scheme_(lenguaje_de_programación)&oldid=1251941794"