Racket se ha desarrollado activamente como herramienta para la investigación de lenguajes de programación desde mediados de la década de 1990 y ha acumulado numerosas características a lo largo de los años. Este artículo describe y demuestra algunas de estas características. Cabe destacar que uno de los principales objetivos de diseño de Racket es facilitar la creación de nuevos lenguajes de programación , tanto lenguajes específicos de dominio como lenguajes completamente nuevos. [ 1 ] Por lo tanto, algunos de los siguientes ejemplos están en otros lenguajes, pero todos están implementados en Racket. Para obtener más información, consulte el artículo principal .
La implementación principal de Racket es muy flexible. Incluso sin usar dialectos, puede funcionar como un lenguaje de scripting completo, capaz de ejecutarse tanto con como sin interfaz gráfica de usuario (GUI) nativa de Windows, y capaz de realizar tareas que van desde la creación de servidores web hasta gráficos.
Soporte en tiempo de ejecución
Recogida de basura, llamadas de seguimiento, seguridad espacial
Racket puede utilizar tres recolectores de basura diferentes :
- Originalmente, se utilizaba el recolector de basura conservador Boehm . Sin embargo, la recolección conservadora resulta poco práctica para procesos de larga duración, como un servidor web, ya que estos tienden a generar fugas de memoria. Además, existen casos críticos en los que un recolector conservador genera fugas de memoria tan rápidas que impiden la ejecución de ciertos programas. Por ejemplo, al recorrer una lista infinita, un simple error de conservación, como retener un puntero, provoca que la lista completa permanezca en memoria, agotando rápidamente la memoria disponible. Este recolector se conoce comúnmente como "CGC" en la comunidad de Racket.
- SenoraGC es un recolector de basura conservador alternativo, diseñado principalmente para la depuración y el rastreo de memoria.
- El gestor de memoria móvil (también conocido como "3m") es un recolector de basura preciso y ha sido el recolector predeterminado de Racket desde 2007. Este recolector es generacional y admite la contabilidad de memoria mediante custodios (véase más abajo). El recolector está implementado como un transformador de código fuente C que, a su vez, está escrito en Racket. Por lo tanto, el proceso de compilación utiliza el recolector conservador para el arranque .
Al igual que todas las implementaciones de la familia Scheme , Racket implementa la eliminación completa de llamadas recursivas . Racket va más allá: el lenguaje es totalmente seguro en cuanto al espacio, mediante el análisis de variables en tiempo real . Esto complementa el preciso recolector de basura y, en algunos casos, como en la implementación de Lazy Racket, ambas características son cruciales para una ejecución correcta. Esto se suma a otras optimizaciones del compilador, como la elevación de expresiones lambda y la compilación justo a tiempo .
Interfaz del sistema y secuencias de comandos
La interfaz del sistema de Racket incluye E/S asíncrona no bloqueante , hilos verdes , canales de sincronización, semáforos, subprocesos y sockets del Protocolo de Control de Transmisión (TCP).
El siguiente programa inicia un "servidor de eco" en el puerto 12345.
#lang raqueta( define listener ( tcp-listen 12345 ))( let echo-server () ;; crea un servidor TCP ( define-values ( in out ) ( tcp-accept listener )) ;; maneja una conexión entrante en un hilo (verde) ( thread ( λ () ( copy-port in out ) ( close-output-port out ))) ;; y vuelve inmediatamente al bucle para aceptar más clientes ( echo-server ))La combinación de compilación dinámica y una rica interfaz de sistema convierte a Racket en un lenguaje de scripting muy capaz, similar a Perl o Python .
El siguiente ejemplo muestra cómo recorrer un árbol de directorios, comenzando en el directorio actual. Utiliza una in-directoryfunción para construir una secuencia que recorre el árbol. La forfunción se vincula patha cada ruta de la secuencia y regexp-match?compara estas rutas con el patrón de expresión regular dado .
#lang racket ;; Busca fuentes de Racket en todos los subdirectorios( para ([ ruta ( en-directorio )]) ; iterar sobre el árbol actual ( cuando ( coincidencia-de-expresión-regular? #rx"[.]rkt$" ruta ) ( printf "archivo fuente: ~a \n " ruta )))El siguiente ejemplo utiliza una tabla hash para registrar las líneas vistas anteriormente e imprimir solo las únicas.
#lang racket ;; Informar cada línea única de stdin( let ([ saw ( make-hash )]) ( for ([ line ( in-lines )]) ( unless ( hash-ref saw line #f ) ( displayln line )) ( hash-set! saw line #t )))Ambos programas pueden ejecutarse en DrRacket o en la línea de comandos mediante el racketejecutable. Racket ignora la línea shebang inicial , lo que permite convertir estos programas en scripts ejecutables. El siguiente script lo demuestra, además de utilizar la biblioteca de Racket para el análisis de argumentos de línea de comandos :
#!/usr/bin/env racket #lang racket( línea de comandos #:args ( directorio base ext re ) ( para ([ p ( en directorio )] #:cuando ( coincidencia de expresión regular? ( cadena-añadir "[.]" ext "$" ) p ) [( número de línea ) ( indexado en ( archivo->líneas p ))]) ( cuando ( coincidencia de expresión regular? ( pregexp re ) línea ) ( printf "~a:~a: ~a~n" p ( + num 1 ) línea ))))El script es una utilidad similar a grep que requiere tres argumentos de línea de comandos: un directorio base, una extensión de archivo y una expresión regular (compatible con Perl). Busca en el directorio base archivos con la extensión especificada e imprime las líneas que coinciden con el patrón de la expresión regular.
Gestión de recursos y entorno aislado (sandboxing)
Racket incorpora el concepto de "custodio": un tipo de valor que actúa como administrador de recursos. Esto se usa frecuentemente en servidores de red, donde cada conexión se gestiona mediante un nuevo custodio, lo que facilita la "limpieza" de todos los recursos que el manejador pudiera haber dejado abiertos (por ejemplo, puertos abiertos). A continuación, se amplía el ejemplo del "servidor de eco" con este uso del custodio:
#lang raqueta( define listener ( tcp-listen 12345 ));; manejador por conexión ( define ( manejador en salida ) ( copiar puerto en salida ) ( cerrar puerto de salida salida ))( let echo-server () ( define-values ( in out ) ( tcp-accept listener )) ( thread ( λ () ( let ([ c ( make-custodian )]) ( parameterize ([ current-custodian c ]) ( handler in out ) ( custodian-shutdown-all c ))))) ( echo-server ))Los administradores de memoria, junto con la función de contabilidad de memoria del recolector de basura 3m y varios parámetros de ejecución adicionales que controlan más aspectos del entorno de ejecución, permiten crear contextos de ejecución aislados completamente seguros. La racket/sandboxbiblioteca proporciona esta funcionalidad de forma sencilla. El siguiente ejemplo crea un servidor REPL ( Read-Eval-Print Loop ) en el puerto especificado; al conectarse a este puerto, se verá como un REPL de Racket normal, con la diferencia de que la evaluación está sujeta a las diversas medidas de protección del entorno aislado. Por ejemplo, no es posible acceder al sistema de archivos desde este REPL, crear conexiones de red, ejecutar subprocesos ni consumir demasiado tiempo o memoria. (De hecho, este REPL es lo suficientemente seguro como para distribuirse públicamente).
#lang racket ( require racket/sandbox ) ( define e ( make-evaluator ' racket/base )) ( let-values ([( i o ) ( tcp-accept ( tcp-listen 9999 ))]) ( parameterize ([ current-input-port i ] [ current-output-port o ] [ current-error-port o ] [ current-eval e ] [ current-read-interaction ( λ ( x in ) ( read in ))]) ( read-eval-print-loop ) ( fprintf o " \ nAdiós... \n " ) ( close-output-port o )))Programación web y de redes
El siguiente ejemplo implementa un servidor web utilizando este web-server/instalenguaje. Cada vez que se establece una conexión con el servidor, startse llama a la función para obtener el código HTML que se enviará de vuelta al cliente.
#lang web-server/insta ;; Un pequeño servidor web "hola mundo"( define ( solicitud de inicio ) ( respuesta/xexpr ' ( html ( cuerpo "Hola Mundo" ))))Racket también incluye las funciones necesarias para escribir web scrapers y robots. Por ejemplo, la siguiente función muestra los resultados de Google para una cadena de búsqueda.
#lang racket ;; Rastreador web simple( requiere net/url net/uri-codec )( define ( let-me-google-that str ) ( let* ([ g "http://www.google.com/search?q=" ] [ u ( string-append g ( uri-encode str ))] [ rx #rx"(?<=<h3 class=\"r\">).*?(?=</h3>)" ]) ( regexp-match* rx ( get-pure-port ( string->url u )))))La biblioteca también incluye soporte para protocolos distintos de http:
#lang racket ;; Enviando una alerta de correo electrónico programada desde racket( requiere net/sendmail )( dormir ( * ( - ( * 60 4 ) 15 ) 60 )) ; esperar 3h 45m( send-mail-message ( getenv "EMAIL" ) "¡Alerta de parquímetro!" ( list ( getenv "EMAIL" )) null null ' ( "Es hora de salir y mover el coche." ))Gráficos
Las capacidades gráficas se presentan en diversas variantes, dirigidas a distintos públicos. La 2htdp/imagebiblioteca ofrece funciones prácticas para la creación de imágenes. Esta biblioteca es utilizada principalmente por estudiantes en cursos basados en el método HtDP ( How to Design Programs ). En el siguiente ejemplo, sierpinskise define y se llama simultáneamente a una función para generar un triángulo de Sierpinski de profundidad 8.
#lang raqueta ;; Una imagen( requiere 2htdp/imagen )( dejar sierpinski ([ n 8 ]) ( si ( cero? n ) ( triángulo 2 ' sólido ' rojo ) ( dejar ([ t ( sierpinski ( -n 1 ) )]) ( congelar ( arriba t ( al lado de t t ))))))Los editores de DrRacket pueden contener imágenes, y DrRacket muestra los valores de las imágenes como cualquier otro tipo de valor (como números enteros o listas). Al ejecutar el programa anterior, por ejemplo, se muestra un triángulo de Sierpinski, que se puede copiar y pegar en otro programa.
La plotbiblioteca construye valores de imagen para audiencias y necesidades más maduras. Por ejemplo, el siguiente programa grafica la suma de dosGaussianas (tridimensionales), como superficies concéntricas parcialmente transparentes:
#lang racket ;; Visualiza la suma de dos gaussianas 3D como isosuperficies concéntricas ;; Nota: este ejemplo requiere Racket 5.2 o posterior( se requiere un gráfico );; Devuelve una función gaussiana R x R x R -> R centrada en (cx,cy,cz) ( define (( gaussian cx cy cz ) x y z ) ( exp ( - ( + ( sqr ( - x cx )) ( sqr ( - y cy )) ( sqr ( - z cz ))))));; Eleva + para operar en funciones de tres argumentos ( define (( f3+ g h ) x y z ) ( + ( g x y z ) ( h x y z )));; Construye un valor de imagen que representa la suma de dos gaussianas ( plot3d ( isosurfaces3d ( f3+ ( gaussiana 0 0 0 ) ( gaussiana 1.5 -1.5 0 )) -1 2.5 -2.5 1 -1 1 #:label "g" )) ; el etiquetado añade una leyendaAquí, la isosurfaces3dfunción requiere una función de tres argumentos para su primer argumento, que es f3+proporcionado por el currificado. Además de construir valores de imagen, plottambién puede escribir archivos en formatos PNG , PDF , PostScript y SVG .
Programación de interfaces gráficas de usuario (GUI)
Racket implementa una capa de interfaz gráfica de usuario ( GUI) portátil sobre la que se basan las bibliotecas mencionadas anteriormente. Se implementa mediante la interfaz de programación de aplicaciones ( API ) nativa de Windows , mediante Cocoa en macOS y mediante GTK + en Linux y otros sistemas. La API de Racket es un conjunto de herramientas basado en clases, con cierta relación con wxWidgets , que se utilizó originalmente.
El siguiente sencillo juego de adivinanzas muestra cómo programar con el kit de herramientas de interfaz gráfica de usuario (GUI). La frame%clase implementa una ventana de nivel superior y button%un botón. La checkfunción definida aquí genera otra función que se utiliza para la acción de devolución de llamada del botón.
#lang racket/gui ;; Un juego de adivinanzas de interfaz gráfica de usuario( define secret ( random 5 ))( define f ( new frame% [ label "Juego de adivinanzas" ])) ; ventana de nivel superior ( define t ( new message% [ parent f ] [ label "¿Puedes adivinar el número en el que estoy pensando?" ])) ( define p ( new horizontal-pane% [ parent f ])) ; contenedor horizontal( define (( make-check i ) btn evt ) ( message-box "." ( cond [( < i secret ) "Demasiado pequeño" ] [( > i secret ) "Demasiado grande" ] [ else "¡Exactamente!" ])) ( when ( = i secret ) ( send f show #f ))) ; success => close window( para ([ i ( en rango 10 )]) ; crear todos los botones ( crear objeto botón% ( formato "~a" i ) p ( hacer comprobación i )))( enviar f mostrar #t ) ; muestra la ventana para iniciar la aplicaciónLa interfaz gráfica de usuario (GUI) se puede codificar manualmente de esta manera o con la ayuda de un programa de diseño de GUI disponible en PLANeT. [ 2 ]
Presentación de diapositivas
También se pueden crear presentaciones de diapositivasslideshow en Racket utilizando el lenguaje, de forma similar a Beamer , pero con las herramientas de programación de Racket. Los elementos de las diapositivas son imágenes que se pueden combinar.
Por ejemplo, el siguiente programa muestra en pantalla completa una diapositiva de título, seguida de una diapositiva con algunas imágenes. Las funciones vc-appendy hc-appendcombinan imágenes vertical y horizontalmente, respectivamente, y centradas en el otro eje.
# presentación de diapositivas de lang( diapositiva ( texto "Presentación de diapositivas" ' romano 56 ) ( texto "Cómo hacer presentaciones en Racket" ' romano 40 ))( diapositiva #:título "Algunas imágenes" ( aplicar vc-append ( para/lista ([ i 5 ]) ( definir ( escala+color p c ) ( colorear ( escala p ( / ( agregar1 i ) 5 )) c )) ( hc-append ( escala+color ( rectángulo-relleno 100 50 ) "azul oscuro" ) ( escala+color ( disco 100 ) "verde oscuro" ) ( escala+color ( flecha 100 ( / pi 6 )) "rojo oscuro" ) )))))También existen paquetes de extensión en PLANeT, [ 2 ] por ejemplo para incluir elementos de LaTeX .
Interfaz de funciones externas
Racket cuenta con una interfaz de funciones externas basada en libffi . Esta interfaz permite escribir código de bajo nivel , similar a C , que puede asignar memoria, desreferenciar punteros, llamar a funciones en bibliotecas compartidas y enviar funciones de devolución de llamada a funciones de Racket (mediante cierres de libffi). La implementación principal es una capa delgada sobre libffi (escrita en C), y la interfaz completa se implementa mediante código Racket. La interfaz utiliza macros de forma extensiva, lo que da como resultado un lenguaje de descripción de interfaz expresivo basado en Racket . Este lenguaje tiene varias características útiles, como la representación uniforme para funciones de orden superior (evitando los problemas que surgen cuando las funciones de devolución de llamada y las llamadas externas son diferentes), definiciones de estructuras similares a las estructuras Racket estándar y tipos de funciones personalizadas que pueden representar punteros de entrada y salida, argumentos implícitos (por ejemplo, un argumento que proporciona el número de elementos en un vector que se pasa como otro argumento). Al usar esta interfaz para acceder a los kits de herramientas GUI subyacentes, Racket implementa su propia capa GUI en Racket. [ 3 ]
La FFI se puede utilizar de varias maneras diferentes: desde escribir una capa de conexión completa para una biblioteca (como se hizo para el enlace OpenGL de Racket ), hasta extraer rápidamente una sola función externa. Un ejemplo de este último enfoque:
#lang racket/base ;; Uso simple de la FFI( requiere ffi/unsafe )( define mci-send-string ( get-ffi-obj "mciSendStringA" "Winmm" ( _fun _string [ _pointer = #f ] [ _int = 0 ] [ _pointer = #f ] -> [ ret : _int ]))) ( mci-send-string "play sound.wav wait" )extensiones de idioma
La característica más destacada de Racket es su capacidad para construir nuevos lenguajes de dominio específico y de propósito general . Esto es el resultado de combinar una serie de características importantes:
- un sistema de módulos flexible que se utiliza para enlazar código y para la gestión de espacios de nombres,
- un extenso sistema de macros —que funciona como una API de compilador— que puede crear nuevas formas sintácticas,
- un sistema de tiempo de ejecución completo, que proporciona características que los implementadores de lenguajes pueden usar, como continuaciones (componibles, delimitadas), administración de recursos, etc.
- una forma de especificar (e implementar) analizadores sintácticos para nuevas sintaxis de lenguaje.
El sistema de módulos desempeña un papel importante a la hora de combinar estas características y de posibilitar la escritura de código que abarca varios módulos, cada uno de los cuales puede estar escrito en un lenguaje diferente.
Estos lenguajes se utilizan ampliamente en la distribución de Racket y en las bibliotecas de usuario. De hecho, crear un nuevo lenguaje es tan sencillo que algunos tienen muy pocos usos.
Racket incluye varios lenguajes útiles, algunos de los cuales son muy diferentes del lenguaje predeterminado de Racket.
Garabato
Scribble, el sistema de documentación de Racket, se presenta en forma de varios lenguajes utilizados para escribir prosa. Se usa para la documentación de Racket, así como para escribir libros y artículos. En realidad, más que un único lenguaje "scribble", se trata de una familia de dialectos (muy similares), cada uno con un propósito diferente.
Para ejecutar el siguiente ejemplo, cópielo en DrRacket y haga clic en uno de los dos botones de renderizado de bocetos que aparecerán (el renderizado de PDF requiere pdfTeX ). Como alternativa, utilice el scribbleejecutable del archivo.
#lang garabato/base @; Genera un documento PDF o HTML usando `scribble`. @(require (planet neil/numspell)) @title{99 Botellas de Cerveza} Por si necesitas algo de @emph{bla bla} en tu vida. @(aplicar lista de elementos) (para/lista ( [n (en rango 99 0 -1) ] ) (define N (número->inglés n)) (define N-- (number->english (sub1 n))) @item{@string-titlecase [N] botellas de cerveza en la pared, @N botellas de cerveza. Toma uno, pásalo, @N-- botellas de cerveza en la pared.})) La característica más llamativa de los lenguajes Scribble es el uso de una nueva sintaxis, diseñada específicamente para código con gran cantidad de texto. [ 4 ] Esta sintaxis permite texto de formato libre, interpolación de cadenas, citas personalizables y resulta útil en otras aplicaciones como el preprocesamiento de texto , la generación de texto y los sistemas de plantillas HTML. Cabe destacar que la sintaxis extiende las expresiones S simples y se implementa como una entrada alternativa para dichas expresiones.
#lang garabato/texto Hola, Soy un archivo de texto; ejecútame. @(define (thrice . text) @list{@text, @text, @text}) @thrice{SPAM}! @thrice{HAM}! Raqueta de escribir
Typed Racket es una variante de Racket con tipado estático . El sistema de tipos que implementa es único, ya que su desarrollo se basó en la intención de incorporar la mayor cantidad posible de código idiomático de Racket; como resultado, incluye subtipos, uniones y mucho más. [ 5 ] Otro objetivo de Typed Racket es permitir la migración de partes de un programa al lenguaje tipado, facilitando así la llamada a código tipado desde código no tipado y viceversa, y generando contratos dinámicos para garantizar invariantes de tipo. [ 6 ] Esta característica se considera deseable en las distintas etapas del ciclo de vida de una aplicación, a medida que evoluciona de "un script" a "una aplicación", donde el tipado estático facilita el mantenimiento de un gran volumen de código.
#lang typed/racket;; Usando tipado de ocurrencia de orden superior ( define-type Str-or-Num ( U String Number ))( : tog (( Lista de Str-or-Num ) -> String )) ( define ( tog l ) ( apply string-append ( filter string? l )))( juntos ( lista 5 "hola " 1/2 "mundo" ( sqrt -1 )))Raqueta perezosa
El lazylenguaje utiliza una semántica de evaluación perezosa , similar a Haskell . En el siguiente ejemplo, fibsse trata de una lista infinita cuyo elemento número 1000 no se calculará hasta que su valor sea necesario para la impresión.
#lang lazy ;; Una lista infinita: ( define fibs ( list* 1 1 ( map + fibs ( cdr fibs ))));; Imprimir el número 1000 de Fibonacci: ( print ( list-ref fibs 1000 ))Programación lógica
Racket incluye tres lenguajes de programación lógica : Racklog, un lenguaje similar a Prolog ; una implementación de Datalog ; y una adaptación de miniKanren . A diferencia de la sintaxis de Scribble, los dos primeros lenguajes utilizan una sintaxis completamente nueva en lugar de una extensión de las expresiones S. Si se utiliza en DrRacket, proporciona resaltado de sintaxis adecuado, la habitual variedad de herramientas para comprobar la sintaxis y una consola interactiva (REPL) de Prolog/Datalog.
#lang datalogantepasado ( A , B ) :- padre ( A , B ). antepasado ( A , B ) :- padre ( A , C ), D = C , antepasado ( D , B ). padre ( john , douglas ). padre ( bob , john ).antepasado ( A , B ) ?Herramientas educativas
El grupo PLT, desarrollador de Racket, se ha dedicado tradicionalmente a la educación en todos los niveles. Una de las primeras ideas de investigación que impulsó fue el uso de niveles de lenguaje, que limitan el progreso de los estudiantes principiantes a la vez que les proporcionan mensajes de error útiles adaptados a su nivel de conocimiento. Este enfoque se utiliza ampliamente en « How to Design Programs » (HtDP), el libro de texto escrito por varios desarrolladores de PLT, y en el proyecto ProgramByDesign . El siguiente programa utiliza el htdp/bsllenguaje para estudiantes principiantes. Emplea la 2htdp/imagebiblioteca para crear imágenes en los lenguajes de enseñanza y la 2htdp/universebiblioteca para animaciones interactivas.
#lang htdp/bsl ;; Cualquier tecla infla el globo( requiere 2htdp/imagen ) ( requiere 2htdp/universo )( define ( globo b ) ( círculo b "sólido" "rojo" ))( definir ( explosión b k ) ( + b 5 ))( define ( deflate b ) ( max ( - b 1 ) 1 ))( big-bang 50 ( explosión en clave ) ( desinflar en tic ) ( globo para dibujar 200 200 ))ALGOL
Racket incluye una implementación completa del lenguaje ALGOL 60 .
# lang algol60 begin integer procedure SIGMA ( x , i , n ) ; value n ; integer x , i , n ; begin integer sum ; sum := 0 ; for i := 1 step 1 until n do sum := sum + x ; SIGMA := sum ; end ; integer q ; printnln ( SIGMA ( q * 2 - 1 , q , 7 )) ; endPlai y plai tipificado
#lang plai#lang plai-typedOtro lenguaje compatible es plai, que al igual que racket puede ser tipado o no tipado. "Los módulos escritos en plai exportan todas las definiciones (a diferencia de scheme)". [ 7 ] "El lenguaje PLAI tipado se diferencia del Racket tradicional principalmente por ser de tipado estático. También proporciona algunas construcciones nuevas útiles: define-type, type-case y test". [ 8 ]
Creación de lenguajes
Finalmente, el siguiente ejemplo es una implementación de un nuevo lenguaje:
#lang racket ( provide ( except-out ( all-from-out racket ) #%top #%app ) ( rename-out [ top #%top ] [ app #%app ])) ( define-syntax-rule ( top . x ) ' x ) ( define-syntax-rule ( app f . xs ) ( if ( hash? f ) ( hash-ref f . xs ) ( f . xs )))Este idioma:
- proporciona todo del
racketidioma, por lo que es una variante algo similar, - excepto por dos "macros de gancho" especiales que implementan la búsqueda de variables no vinculadas y llamadas a funciones, en lugar de estas, se proporcionan nuevas formas para
- citar implícitamente todas las variables desconocidas
- permitir que las tablas hash se utilicen como funciones, donde los argumentos se utilizan para la búsqueda en la tabla hash. [ 9 ]
Si este código se almacena en un mylang.rktarchivo, se puede utilizar de la siguiente manera:
#lang s-exp "mylang.rkt" ; sintaxis de sexpr, usando la semántica de mylang ( define h ( make-hasheq )) ( hash-set! h A B ) ; A y B se autoevalúan aquí ( h A ) ; la tabla hash se usa como una funciónReferencias
- ↑ Tobin-Hochstadt, S.; St-Amour, V.; Culpepper, R.; Flatt, M.; Felleisen, M. (2011). "Lenguajes como bibliotecas" (PDF) . Diseño e implementación de lenguajes de programación .
- 1 2 PLANeT : Sistema centralizado de distribución de paquetes de Racket
- ↑ "Reconstruyendo la capa gráfica de Racket" . 8 de diciembre de 2010. Archivado del original el 2 de febrero de 2013. Consultado el 7 de julio de 2013 .
- ↑ Barzilay, E. (2009). "The Scribble Reader" (PDF) . Scheme y programación funcional .
- ↑ Tobin-Hochstadt, S.; Felleisen, M. (2008). "El diseño e implementación de esquemas tipados". Principios de lenguajes de programación .
- ↑ Tobin-Hochstadt, S.; Felleisen, M. (2006). "Migración entre lenguajes: de scripts a programas". Simposio de Lenguajes Dinámicos .
- ↑ "1 Esquema PLAI" .
- ↑ Krishnamurthi, Shriram. "Lenguajes de programación: aplicación e interpretación". Lenguajes de programación: aplicación e interpretación. Universidad de Brown, s.f. Web. 14 de marzo de 2016. < https://cs.brown.edu/courses/cs173/2012/book/ >.
- ↑ Cabe destacar que
#%appse trata de una macro que se utiliza en todas las llamadas a funciones, lo que hace que este lenguaje no sea muy eficiente, ya que cada llamada a función implica una condición adicional. Además, la macro evalúa la expresión de la función dos veces, por lo que no debe considerarse un buen ejemplo de programación con macros.
- Al momento de esta edición , este artículo utiliza contenido de "Racket" , cuya licencia permite su reutilización bajo la Licencia Creative Commons Atribución-CompartirIgual 3.0 No Adaptada , pero no bajo la GFDL . Deben respetarse todos los términos pertinentes.
Enlaces externos
- Sitio web oficial
- documentos.racket
- Desarrollo de software
- banco de trabajo de lenguaje