Scheme vs Common Lisp: ¿Qué características marcaron la diferencia en su proyecto? [cerrado]

155

No faltan las preguntas vagas de "Esquema versus Common Lisp" tanto en StackOverflow como en este sitio, por lo que quiero enfocarlo más. La pregunta es para las personas que han codificado en ambos idiomas:

Mientras codificaba en Scheme, ¿qué elementos específicos de su experiencia de codificación Common Lisp extrañaba más? O, inversamente, mientras codificaba en Common Lisp, ¿qué extrañó de la codificación en Scheme?

No necesariamente me refiero solo a las características del lenguaje. Las siguientes son cosas válidas que debe perderse, en lo que respecta a la pregunta:

  • Bibliotecas específicas
  • Características específicas de entornos de desarrollo como SLIME, DrRacket, etc.
  • Características de implementaciones particulares, como la capacidad de Gambit de escribir bloques de código C directamente en su fuente de Scheme.
  • Y, por supuesto, las características del lenguaje.

Ejemplos del tipo de respuestas que espero:

  • "Estaba tratando de implementar X en Common Lisp, y si tuviera las continuaciones de primera clase de Scheme, habría hecho totalmente Y, pero en lugar de eso tuve que hacer Z, lo que fue más doloroso".
  • "La creación de secuencias de comandos en el proceso de compilación en mi proyecto Scheme se volvió cada vez más dolorosa a medida que mi árbol fuente creció y me vinculé a más y más bibliotecas C. Para mi próximo proyecto, volví a Common Lisp".
  • "Tengo una gran base de código C ++ existente, y para mí, poder incrustar llamadas C ++ directamente en mi código de Gambit Scheme valió totalmente cualquier deficiencia que Scheme pueda tener frente a Common Lisp, incluso la falta de soporte SWIG".

Entonces, espero historias de guerra, en lugar de sentimientos generales como "El esquema es un lenguaje más simple", etc.

Súper eléctrico
fuente
25
Una excelente pregunta bien redactada. Tengo curiosidad por esto yo mismo; Esperemos que haya algunas personas con experiencia en ambos idiomas que estén dispuestas a proporcionar alguna información.
Robert Harvey
1
@ Josh K: es claramente responsable, pero no necesariamente hay una única respuesta definitiva. ¡Excepto que apuesto a que habrá una porque alguien saldrá con una respuesta que es tan increíble que todos son como whoa!
glenatron
44
@ Josh: Entonces quizás no estés familiarizado con Scheme y Common Lisp. Ambos idiomas son muy poderosos por derecho propio, sin embargo, ninguno de los dos tiene aceptación general. ¿Por qué es esto? Podría ser porque hay tantos dialectos; ¿Cuál eliges? Una comparación de este tipo podría ser muy esclarecedora, y el OP ha redactado cuidadosamente la pregunta para limitar el alcance a las respuestas que, en mi opinión, son muy específicas y responden.
Robert Harvey
13
Amigos, no cierren la pregunta solo porque no les gusta o no pueden relacionarse con ella. Es claramente una pregunta "real"; Si no puede encontrar una mejor razón para cerrarlo, no debería votar para cerrarlo.
Robert Harvey
44
Podrías enviarle un correo electrónico a Richard Stallman por su respuesta.
wassimans

Respuestas:

100

Mi licenciatura fue en Ciencia Cognitiva e Inteligencia Artificial. A partir de eso tuve una introducción de un curso a Lisp. Pensé que el lenguaje era interesante (como en "elegante") pero realmente no lo pensé mucho hasta que encontré la Décima Regla de Greenspun mucho más tarde:

Cualquier programa C o Fortran suficientemente complicado contiene una implementación ad hoc, especificada informalmente, llena de errores y lenta de la mitad de Common Lisp.

El punto de Greenspun fue (en parte) que muchos programas complejos tienen intérpretes incorporados. En lugar de construir un intérprete en un idioma, sugirió que podría tener más sentido usar un lenguaje como Lisp que ya tiene un intérprete (o compilador) incorporado.

En ese momento, había estado trabajando en una aplicación bastante grande que realizaba cálculos definidos por el usuario utilizando un intérprete personalizado para un idioma personalizado. Decidí intentar reescribir su núcleo en Lisp como un experimento a gran escala.

Tomó aproximadamente seis semanas. El código original era ~ 100,000 líneas de Delphi (una variante de Pascal). En Lisp eso se redujo a ~ 10,000 líneas. Sin embargo, aún más sorprendente fue el hecho de que el motor Lisp era 3-6 veces más rápido. ¡Y tenga en cuenta que este fue el trabajo de un neófito Lisp! Toda esa experiencia me abrió los ojos; Por primera vez, vi la posibilidad de combinar rendimiento y expresividad en un solo idioma.

Algún tiempo después, cuando comencé a trabajar en un proyecto basado en la web, audicioné varios idiomas. Incluí Lisp y Scheme en la mezcla. Al final, seleccioné una implementación de Esquema : Esquema Chez . He estado muy contento con los resultados.

El proyecto basado en la web es un "motor de selección" de alto rendimiento . Utilizamos Scheme de varias maneras diferentes, desde el procesamiento de datos hasta la consulta de datos y la generación de páginas. En muchos lugares, en realidad comenzamos con un idioma diferente, pero terminamos migrando a Scheme por razones que describiré brevemente a continuación.

Ahora puedo responder a tu pregunta (al menos en parte).

Durante la audición, observamos una variedad de implementaciones de Lisp y Scheme. En el lado de Lisp vimos (creo) Allegro CL, CMUCL, SBCL y LispWorks. En el lado del Esquema miramos (creo) Bigloo, Chicken, Chez, Gambit. (La selección del idioma fue hace mucho tiempo; por eso estoy un poco confusa. Puedo desenterrar algunas notas si es importante).

Inmediatamente estábamos buscando a) hilos nativos yb) soporte para Linux, Mac y Windows. Esas dos condiciones combinadas noquearon a todos, pero (creo) Allegro y Chez, así que para continuar con la evaluación tuvimos que aflojar el requisito de subprocesos múltiples.

Creamos un conjunto de pequeños programas y los usamos para evaluación y pruebas. Eso reveló una serie de problemas. Por ejemplo: algunas implementaciones tenían defectos que impedían que algunas pruebas se ejecutaran hasta su finalización; algunas implementaciones no pudieron compilar código en tiempo de ejecución; algunas implementaciones no podían integrar fácilmente el código compilado en tiempo de ejecución con el código precompilado; algunas implementaciones tenían recolectores de basura que eran claramente mejores (o claramente peores) que las otras '; etc.

Para nuestras necesidades, solo las tres implementaciones comerciales, Allegro, Chez y Lispworks, pasaron nuestras pruebas principales. De los tres, solo Chez pasó todas las pruebas con gran éxito. En ese momento, creo que Lispworks no tenía hilos nativos en ninguna plataforma (creo que sí) y creo que Allegro solo tenía hilos nativos en algunas plataformas. Además, Allegro tenía una tarifa de licencia de "llámenos" en tiempo de ejecución que no me gustó mucho. Creo que Lispworks no tenía una tarifa de tiempo de ejecución y Chez tenía un acuerdo directo (y muy razonable) (y solo funcionaba si usabas el compilador en tiempo de ejecución).

Después de haber producido fragmentos de código algo significativos tanto en Lisp como en Scheme, aquí hay algunos puntos de comparación y contraste:

  • Los entornos de Lisp son mucho más maduros. Obtienes mucho más por el dinero. (Dicho esto, más código también equivale a más errores).

  • Los entornos de Lisp son mucho más difíciles de aprender. Necesitas mucho más tiempo para ser competente; Common Lisp es un lenguaje enorme, y eso es antes de llegar a las bibliotecas que las implementaciones comerciales agregan. (Dicho esto, el caso de sintaxis de Scheme es mucho más sutil y complicado que cualquier otra cosa en Lisp).

  • Los entornos Lisp pueden ser algo más difíciles de producir binarios. Necesita "sacudir" su imagen para eliminar bits innecesarios, y si no ejercita su programa correctamente durante ese proceso, podría terminar con errores de tiempo de ejecución más adelante. . Por el contrario, con Chez compilamos un archivo de nivel superior que incluye todos los demás archivos que necesita y listo.

Dije antes que terminamos usando Scheme en varios lugares que originalmente no teníamos intención. ¿Por qué? Puedo pensar en tres razones fuera de mi cabeza.

Primero, aprendimos a confiar en Chez (y su desarrollador, Cadence). Pedimos mucho de la herramienta, y se entregó constantemente. Por ejemplo, Chez ha tenido históricamente un número trivialmente pequeño de defectos, y su administrador de memoria ha sido muy, muy bueno.

En segundo lugar, aprendimos a amar la actuación que obtuvimos de Chez. Estábamos usando algo que parecía un lenguaje de scripting, y estábamos obteniendo la velocidad del código nativo. Para algunas cosas que no importaban, pero nunca dolían, y a veces ayudaban muchísimo.

Tercero, aprendimos a amar la abstracción que el Esquema podría proporcionar. No me refiero solo a las macros, por cierto; Me refiero a cosas como cierres, lambdas, llamadas de cola, etc. Una vez que empiezas a pensar en esos términos, otros idiomas parecen bastante limitados en comparación.

¿Es el esquema perfecto? No; Es una compensación. Primero, permite que los desarrolladores individuales sean más efectivos, pero es más difícil para los desarrolladores asimilar el código de los demás porque faltan las señales que tienen la mayoría de los idiomas (por ejemplo, para bucles) en Scheme (por ejemplo, hay un millón de formas de hacerlo un bucle for). En segundo lugar, hay un grupo mucho más pequeño de desarrolladores para hablar, contratar, pedir prestado, etc.

Para resumir, creo que diría: Lisp y Scheme ofrecen algunas capacidades que no están ampliamente disponibles en ningún otro lugar. Esa capacidad es una compensación, por lo que es mejor que tenga sentido en su caso particular. En nuestro caso, los factores determinantes entre ir con Lisp o Scheme tenían más que ver con características muy fundamentales (soporte de plataforma, subprocesos de plataforma, compilación en tiempo de ejecución, licencias en tiempo de ejecución) que con las funciones de idioma o biblioteca. Nuevamente, en nuestro caso eso también fue una compensación: con Chez obtuvimos las características principales que queríamos, pero perdimos las amplias bibliotecas que tenían los entornos comerciales de Lisp.

Además, solo para reiterar: observamos los diversos Lisps y Esquemas hace mucho tiempo; Todos han evolucionado y mejorado desde entonces.

Michael Lenaghan
fuente
1
¡Guau, eso debe haber sido un código de Delphi realmente horrible si de alguna manera logró funcionar 3-6 veces más lento que una implementación de Lisp! :(
Mason Wheeler
2
+1: Lo más interesante de esta publicación es el hecho de que cambiaste de Lisp a Scheme después de realizar un gran proyecto en Lisp. (O tal vez solo he estado al acecho en comp.lang.lisp demasiado tiempo).
Larry Coleman
25
"¡Wow, eso debe haber sido un código de Delphi realmente horrible si de alguna manera logró funcionar 3-6 veces más lento que una implementación de Lisp!" Bien, lo contaré como mi fracaso por no explicarlo mejor. La implementación de Lisp fue capaz de transformar las expresiones de usuario en expresiones de Lisp, un proceso trivialmente fácil, y luego compilar las expresiones de Lisp en código nativo (con optimización completa). Ese es el significado de la Décima Regla de Greenspun.
Michael Lenaghan
1
Fantástica respuesta! Lo elegiré, al menos hasta que aparezca uno mejor :) Una pregunta: dices que tomaste la decisión de ir con Chez Scheme en función del estado del campo "hace mucho tiempo". ¿Podría especificar un año?
SuperElectric
11
Ese punto, que la implementación de LISP es libre de compilar algo en código máquina, en lugar de depender de un intérprete, es sutil y bastante útil. El libro "Let Over Lambda" señala que esta es precisamente la razón por la cual el paquete portátil de expresión regular Common LISP, que clona la sintaxis de expresión regular PERL, supera a PERL en un factor significativo. PERL, abajo, tiene un intérprete regexp. El paquete Common LISP compila las expresiones regulares en código.
John R. Strohm
37

Por lo general, no me gusta pegar un enlace como respuesta, pero escribí un artículo de blog sobre esto mismo. No es exhaustivo, pero logra algunos de los puntos principales.

http://symbo1ics.com/blog/?p=729

Editar : Aquí están los puntos principales:

  1. EXISTENCIA : Ambos lisps se produjeron después de un montón de otros lisps. Scheme tomó la ruta mínima y axiomática. CL tomó la ruta barroca.
  2. CASO : Normalmente, el esquema distingue entre mayúsculas y minúsculas. CL no lo es (aunque puede serlo). Esto a veces se pierde, pero su practicidad es debatida (por mí).
  3. NOMBRES : Los nombres de los símbolos en CL son muchas veces extraños y confusos. TERPRI, PROGNetc. El esquema generalmente tiene nombres muy sensibles. Esto es algo perdido en CL.
  4. FUNCIONES : CL tiene un espacio de nombres de función separado. Esto no se pierde en Scheme. Tener un solo espacio de nombres generalmente permite una programación funcional muy limpia, que a menudo es difícil o incómoda en CL. Pero tiene un costo --- a veces tienes que ofuscar nombres como " list" a " lst" en Scheme.
  5. MACROS : Extraño las macros sucias de bajo nivel más en Scheme. Sí, syntax-rulestodo está bien y elegante hasta que realmente quieras hackear algunas cosas. Por otro lado, las macros higiénicas a veces se pierden en CL. No tener una forma estándar de hacerlo significa reinventar la rueda.
  6. PORTABILIDAD : a menudo ocurre que CL es más portátil, a pesar de que ambos idiomas están estandarizados. CL es más grande y, por lo tanto, hay más funciones estándar para usar sin bibliotecas externas. También significa que se pueden hacer cosas más dependientes de la implementación de forma portátil. Además, Scheme sufre de tener un billón de implementaciones, la mayoría de las cuales son algo incompatibles. Esto hace que CL sea muy deseable.
  7. BIBLIOTECAS : Muy relacionado con mi último punto. El esquema tiene SRFI pero no se reconoce universalmente. No hay una forma portátil de trabajar con bibliotecas. CL por otro lado tiene formas. Y Quicklisp es un regalo de dios (Xach), una especie de repositorio de bibliotecas para su uso.
  8. IMPLEMENTACIONES : El esquema adolece de tener tantas implementaciones. No existe una implementación canónica real. CL, por otro lado, tiene algunas implementaciones de alto rendimiento o de uso específico muy buenas (alto rendimiento: SBCL, comercial: Allegro, integrado: ECL, portátil: CLISP, Java: ABCL, ...).

Si bien solo hablé en primera persona un poco más arriba, debería quedar claro lo que extraño y lo que no.

[Me disculpo si son demasiado generales. Parece que quieres muchos detalles más específicos. Hay algunos detalles en la publicación.]

Cuadrescencia
fuente
¿qué pasa con un resumen (realmente) corto? ^^
Dave O.
2
Por favor, en línea los aspectos más destacados. Las respuestas deben ser independientes.
1
@Dave O. y @ Thorbjørn Ravn Andersen: se agregó un resumen según lo solicitado. Gracias.
Quadrescence
2
"La ruta barroca"! Qué excelente manera de decirlo.
Mark C
Common Lisp distingue entre mayúsculas y minúsculas, pero convierte su entrada en mayúsculas antes de evaluarla. Puede obtener letras minúsculas en los símbolos entre comillas. El problema del nombre se debe a que Scheme se deshizo de los viejos nombres malos y CL no.
David Thornley
25

Recientemente comencé un proyecto de inicio usando una biblioteca que tiene una versión C y una versión Java. Quería usar Lisp para el proyecto, y pasé alrededor de un mes vacilando entre usar Common Lisp, Scheme o Clojure. Tengo algo de experiencia con los tres, pero solo proyectos de juguetes. Te contaré un poco sobre mi experiencia con cada uno de ellos antes de decirte cuál elegí.

PLT Racket tiene un buen IDE que no solo le permite evaluar expresiones del editor, sino que también le permite escribir corchetes en lugar de parens, volviéndolos a los parens cuando sea apropiado. Racket también tiene un gran conjunto de bibliotecas con la instalación y aún más disponibles para descargar. El depurador visual también es útil.

Mi implementación de Common Lisp (SBCL) no tiene un IDE, pero es habitual que las implementaciones de código abierto de CL utilicen Emacs y SLIME. Esta combinación puede ser muy eficiente. Junto con la capacidad de evaluar expresiones a medida que las escribe en el archivo fuente, también hay un REPL que tiene todos los comandos de edición de emacs disponibles, por lo que la copia de código puede ser eficiente en ambos sentidos. Incluso los objetos que se muestran en el búfer REPL se pueden copiar y pegar. Alt+(y Alt+)son eficientes para tratar con paréntesis y sangría coincidentes.

Todas las características anteriores de Emacs también están disponibles para Clojure. Mi experiencia de edición con Clojure es similar a la de Lisp. La interoperabilidad de Java funcionó bien, y me gustaría hacer un proyecto Clojure una vez que madure.

Pude acceder a la biblioteca usando los tres (Common Lisp, Racket y Clojure), pero terminé eligiendo Common Lisp para el proyecto. El factor decisivo fue que el FFI era mucho más fácil de usar en Common Lisp. CFFI tiene un muy buen manual con código de ejemplo y explicaciones detalladas de cada método. Pude ajustar 20 funciones C en una tarde y no he tenido que tocar el código desde entonces.

El otro factor fue que estoy más familiarizado con Common Lisp que con Clojure o R6RS Scheme. He leído la mayoría de los libros Practical Common Lisp y Graham, y me siento cómodo con el Hyperspec. Todavía no es un código muy "lispy", pero estoy seguro de que cambiará a medida que gane más experiencia.

Larry Coleman
fuente
Gracias por el detalle! ¿Te entiendo correctamente que creías que el FFI de SBCL era más fácil de usar que el de Clojure? Si es así, estaría bastante sorprendido por eso, dado que puede llamar a los métodos Java directamente desde Clojure sin tener que ajustarlos. (¿O también necesitaba llamar al código nativo?)
SuperElectric
66
@SuperElectric: Llamar a los métodos Java "incorporados" desde Clojure es trivial; llamar a métodos Java que están en una biblioteca descargada: no tanto. Realmente pasé más tiempo obteniendo el classpath e importando líneas correctamente de lo que me llevó obtener mi primer método C trabajando desde SBCL con CFFI. Pero no soy un experto en Java, por lo que su kilometraje puede variar.
Larry Coleman
21

Programa en CL y Racket.

Estoy desarrollando un sitio web ahora en Common Lisp, y escribí un conjunto de programas internos para mi empleador anterior en Racket.

Para el código interno, elegí Racket (entonces conocido como PLT Scheme) porque el empleador era una tienda de Windows, y no pude hacer que pagaran por LispWorks. La única buena implementación de CL de código abierto para Windows fue (y sigue siendo) CCL, que requiere soporte SSE en el procesador. El empleador, siendo barato, estaba usando hardware de la Edad de Piedra. Incluso si el empleador tenía un hardware decente, la única biblioteca GUI de consecuencia en Common Lisp es McCLIM, que solo funciona en Unix. Racket tiene una buena biblioteca GUI que funciona tanto en Unix como en Windows, lo que fue fundamental para el éxito de mi proyecto.

Pasé más de un año soportando el primitivo editor DrRacket. EMACS no pudo convertir la versión GUI de Racket, entonces conocida como MrEd, en un lisp inferior en Windows. Tuve que hacerlo sin poder evaluar la expresión en el cursor con una sola pulsación de tecla. En cambio, tuve que seleccionar manualmente la expresión S, copiarla, hacer clic en la ventana REPL (porque no hay pulsación de teclas para cambiar a ella) y luego pegar la expresión S. También tuve que prescindir de un editor que me mostrara los argumentos esperados de la función o macro que estaba usando. DrRacket no sustituye a SLIME.

El empleador estaba usando una base de datos patentada con una API XML complicada que requería cargas de información aparentemente innecesaria para poder responder a su versión de una consulta SELECT. Decidí usar HTMLPrag tanto para emitir XML a esta API como para analizar las respuestas. Funcionó muy bien.

Tuve que aprender el sistema de macro "caso de sintaxis" demasiado complicado de Racket para escribir una macro que me permitiera interactuar con la API XML demasiado complicada escribiendo formularios que parecían SQL. Esta parte habría sido mucho más fácil si tuviera DEFMACRO a mi disposición. Sin embargo, el resultado final aún fue perfecto a pesar de que tomó más esfuerzo lograrlo.

Además, tuve que prescindir de la macro LOOP de Common Lisp. Racket comenzó a proporcionar una alternativa solo después de haber escrito la mayor parte del código, y la alternativa todavía apesta en comparación con LOOP (aunque el equipo de desarrollo de Racket insiste en que es mejor, simplemente están equivocados). Terminé escribiendo muchos formularios LET con nombre que usaban "car" y "cdr" para iterar sobre las listas.

Hablando de car y cdr, nada es más frustrante que la interpretación de Scheme de (car '()) como un error. Aproveché la distinción entre mayúsculas y minúsculas de Racket e implementé CAR y CDR, que tienen la semántica de Common Lisp. Sin embargo, la separación de '() y #f hace que sea mucho menos útil devolver' () como valor predeterminado.

También terminé implementando UNWIND-PROTECT e inventé mi propio sistema de reinicio para llenar el vacío dejado por Racket. La comunidad Racket necesita aprender que los reinicios son muy útiles y fáciles de implementar.

El formulario let-values ​​de Racket era demasiado detallado, así que implementé MULTIPLE-VALUE-BIND. Esto era absolutamente necesario, porque Racket requiere que reciba todos los valores que se generan, ya sea que los use o no.

Más tarde, intenté escribir un cliente de API XML de eBay en Common Lisp, solo para descubrir que no tiene nada como HTMLPrag. HTMLPrag es jodidamente útil. Terminé haciendo ese proyecto en Racket. Experimenté con las instalaciones de programación literaria de Racket, solo para descubrir que soy el único programador en la Tierra que encuentra el código alfabetizado correctamente escrito más difícil de editar que el código ordinario, o el código alfabetizado de "comentarios excesivos" incorrectamente escrito.

Mi nuevo proyecto se está realizando en Common Lisp, que fue la elección correcta porque la comunidad Racket simplemente no cree en el paralelismo, que es esencial para este proyecto. Lo único que pensé que podría haber extrañado de Racket fueron las continuaciones. Sin embargo, pude hacer lo que necesitaba usando reinicios y, en retrospectiva, probablemente podría haberlo hecho con un simple cierre.

Chantajista
fuente
2
No lo he probado yo mismo, pero he visto publicaciones de blog de personas que usan el programa de raquetas de línea de comandos con Emacs. Por ejemplo: bc.tech.coop/scheme/scheme-emacs.htm
Larry Coleman
55
Para ser justos, parece que viniste a Scheme con ganas de escribir CL en lugar de tratar de abordar las cosas desde un POV de Scheme idiomático. Por ejemplo, ¿el esquema no fomenta la recurrencia en lugar de usar bucles?
Trineo
@ArtB Scheme no solo fomenta la recursividad, sino que también lo requiere , por lo que, por supuesto, el proyecto mencionado anteriormente utilizó mucha recursividad. Y eso solo sirvió para agregar repetición (debe incluir una copia de la llamada recursiva en cada rama de un condformulario, por ejemplo) y errores (¿escribí la prueba de terminación de bucle correctamente esa vez?) Incluso hoy, tengo la impresión esa Raqueta está destinada principalmente a estudiantes y no a programadores profesionales. Cada vez que escucho que alguien además de mí lo está usando, está usando el sublenguaje "Estudiante principiante" y es para una clase.
Deseche la cuenta el
Si está repitiendo código en COND, ¿está diciendo que solo necesita otra función?
Trineo
@ArtB ¿Una función para llamar a la función de bucle con diferentes argumentos? Eso sería un poco inútil. Ves ese tipo de repetición en casi el código Scheme de cualquiera. Incluso hay ejemplos en el propio código fuente de Racket.
Deseche la cuenta el
5

Scheme está diseñado con una compilación separada en mente. Como consecuencia, el poder de sus macros a menudo se ve severamente limitado, incluso con las extensiones que permiten un defmacro de estilo Lisp común en lugar de un sistema macro higiénico pobre y limitante. No siempre es posible definir una macro que defina otra macro, destinada a un uso inmediato en la siguiente línea de código. Y esa posibilidad es esencial para implementar compiladores eDSL eficientes.

No hace falta mencionar que las implementaciones de Scheme con solo macros higiénicas R5RS son apenas útiles para mí, ya que mi estilo de metaprogramación no puede traducirse adecuadamente en higiene.

Afortunadamente, hay implementaciones de Scheme (por ejemplo, Racket) que no tienen esa limitación.

SK-logic
fuente
1
Hola, recientemente comencé a mojarme los pies con Scheme recientemente usando Racket. ¿Le importaría proporcionar un ejemplo rápido del uso de macros no higiénicas en Racket? El tipo de macros disponibles parece uno de los puntos más debatidos entre CL y Scheme.
orange80
@ orange80, el único enfoque es usar docs.racket-lang.org/mzlib/mzlib_defmacro.html Y, por supuesto, en modo R6RS hay una forma menos restrictiva.
SK-logic
@ SK-logic ¿qué estás haciendo con macros que es tan antihigénico?
Trineo
1
@ArtB, estoy implementando eDSL como funciones de compilación que pueden hacer bastante con su fuente AST. La higiene es una molestia total dentro de este enfoque. Puede echar un vistazo a cómo funciona: github.com/combinatorylogic/mbase
SK-logic