La décima regla de Greenspun (en realidad la única regla) establece que:
Any sufficiently complicated C or Fortran program contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp.
Mi memoria es que hay algunos documentos sobre el tema, tal vez para el proyecto Quattro (hoja de cálculo) de Borland y posiblemente otros. Google no es útil, tal vez no se te ocurran los términos de búsqueda correctos. Estoy buscando documentos o artículos que respalden esta afirmación, si corresponde.
c
language-design
lisp
fortran
casualcoder
fuente
fuente
Respuestas:
La declaración es una hipérbole. Pero hay signos obvios de envidia de Lisp en otros idiomas. Mire C # y cómo se está volviendo más funcional en la naturaleza. Observe los diversos marcos de Business Process Management, workflow y EAI que hacen todo lo posible para que sea posible programar el sistema sin cambiar el programa.
Hay un libro sobre lenguajes específicos de dominio de Martin Fowler que habla sobre cómo hacer metaprogramación en lenguajes orientados a objetos. Entonces hay algo de verdad en la hipérbole.
Paul Graham calificó a Lisp como el lenguaje más poderoso al observar la lista de los primeros que vinieron con Lisp , es fácil ver por qué muchos idiomas palidecen en comparación.
El camino alrededor de la décima regla es la programación políglota. Al darse cuenta de que un idioma / marco no es el martillo de oro. Luego, en lugar de crear una implementación pobre y ad hoc de Lisp, puede usar Lisp.
fuente
La "décima regla" de Greenspun fue un poco snark. Cuando se estira lo suficiente, si hace que cubra "cualquier sistema de script o configuración", entonces obviamente la respuesta a esta pregunta tendrá que ser "sí", ya que la configuración es algo que cualquier programa no trivial requiere en algún grado, y el script es solo un poco menos común a medida que avanza la escala de complejidad.
Por otro lado, eche un vistazo a GOAL , una variante de Lisp inventada por Naughty Dog para la programación de juegos. No se parece mucho a Lisp "clásico". Es un sistema de estilo altamente imperativo, con funcionalidad orientada a objetos, sin intérprete, soporte mínimo para la recolección de basura (confiando en su lugar en instalaciones de limpieza de nivel de tiempo de ejecución) y amplio soporte para ensamblaje en línea.
En otras palabras, cuando intentaron usar Lisp para un proyecto suficientemente complejo, ¡descubrieron que para hacer algo útil tenían que convertir el lenguaje en una implementación ad-hoc, especificada informalmente de la mitad de C ++! ;) (Y finalmente tuvieron que dejar de usarlo después de que el tipo que diseñó GOAL se fue, porque nadie podía entender su código).
fuente
Curiosamente, una respuesta a esta pregunta ya está en Programmers SE .
Para citar la parte relevante:
Para aclarar aún más esa parte, Michael respondió a un comentario con:
Dado que esta respuesta se compone de la respuesta de otra persona en otra parte, es una wiki comunitaria.
fuente
La regla es una broma, pero hay un poco de verdad en ella. Cualquier sistema complejo contendría una cantidad de partes interpretadas (vea, cómo el "patrón de intérprete" es popular entre aquellos que creen en todos esos patrones mumbo-jumbo). Cualquier sistema complejo debe proporcionar algunos medios de configuración, a menudo estructurados, a menudo interpretados.
Es muy probable que cualquier sistema complejo tenga varios pases de generación de código y varios preprocesadores personalizados en su proceso de construcción (piense en cosas como
moc
en Qt otablegen
en LLVM).Muchos sistemas están haciendo malabarismos con las complejas estructuras de datos en forma de árbol utilizando un conjunto (casi siempre) de herramientas para caminar y transformar árboles mal diseñadas, que se parecen mucho a la funcionalidad de la biblioteca de Common Lisp.
Todas estas cosas vienen gratis con Lisp, y en la mayoría de los casos, todas esas implementaciones ad hoc, no planificadas, no pensadas a fondo, serían completamente inferiores.
fuente
Cualquier sistema suficientemente complejo tendrá conceptos y requisitos específicos del dominio que son extremadamente difíciles de expresar con las abstracciones del lenguaje en el que está trabajando. Esto inadvertidamente obliga a los programadores a crear abstracciones específicas del dominio para aliviar la carga de cerrar la brecha semántica entre el lenguaje de programación y el dominio específico. Una vez que hay suficientes de estas abstracciones, básicamente tienes un intérprete de un lenguaje específico de dominio. Esta es una parte inevitable del desarrollo de software.
fuente
La regla probablemente podría ser más precisa (y menos divertida) ya que "se requerirá que cada sistema basado en software grande implemente un comportamiento dinámico".
Esto se puede hacer de dos maneras-
Un gran archivo de configuración complejo con docenas de parámetros y cientos de definiciones.
Un lenguaje de script AD-HOC.
"sendmail" es probablemente el ejemplo canónico del tipo "1". No puedo pensar en ningún buen ejemplo de tipo "2" que no implique la incorporación de un lenguaje de script "real" a la Warcraft / LUA o incluso Netscape / Javascript.
El problema es que, para algunos parámetros, es rápido y sencillo hacerlo con un archivo de configuración, pero esta solución realmente no escala. Sin embargo, en ningún momento será económico volcar el archivo de configuración a favor de un enfoque de script al agregar una o dos opciones al archivo de configuración. Entonces, el código que interpreta el archivo de configuración acaba siendo un intérprete muy mal escrito.
fuente
Eso puede ser cierto, como otros han dicho, muchos programas requieren configurabilidad y, por lo tanto, contienen varios intérpretes tipo lisp.
Sin embargo, la declaración también implica con una sonrisa que todo lo que necesita para hacer un programa es Lisp, y que todos los demás lenguajes son inferiores.
Pero está mal, Lisp puede ser expresivo, pero también es demasiado abstracto, trata de ocultar detalles de una plataforma y simula que solo existen listas en el mundo de las computadoras.
La realidad de la programación de alto rendimiento es que a veces necesitamos mezclarnos con bits y bytes, y hacer cosas específicas del sistema operativo, por lo que no es posible hacer todo solo con Lisp como lo implica la declaración.
Es más bien al revés, no importa cuán complicado, inteligente o sofisticado sea el lenguaje que inventes, todo lo que termina siendo es simplemente otra forma de escribir ensamblado.
fuente
Ya sea que haya sido tomado en serio o no, es cierto para los proyectos C y C ++ más grandes en los que he trabajado.
Lo que no es cierto es que los lenguajes de script personalizados se parecen a Common Lisp. Los ejemplos positivos se asemejan a Scheme (porque los diseñadores más inteligentes integraron Guile, SpiderMonkey y Lua en lugar de inventar su propio idioma). Los ejemplos más dignos de DailyWTF fueron un lenguaje similar a Forth y un lenguaje similar a MUMPS.
Otro ejemplo (no estoy seguro si cuenta como Greenspunning, pero ciertamente un WTF) fue un intérprete XSLT utilizado para secuencias de comandos de propósito general. Esto era más parecido a Lisp, ya que agregaron un ciclo de retroalimentación donde la salida se transformaría XSLT por segunda vez, por lo que ahora tiene macros de manera efectiva.
Sin embargo, el motivo aquí no era obtener acceso a las funciones de lispy, sino eludir los procedimientos de control de calidad del código de la empresa (que agregaban 3 semanas de latencia a cada corrección de errores. XML se consideraba "datos" y estaba exento del proceso).
fuente
¡Lamentablemente no!
Si bien es mejor integrar un intérprete real de lisp (y) (javascript o lua alos hace un buen trabajo), agregar un homebrew 4gl a un proyecto reduce el tamaño general al tiempo que aumenta la flexibilidad.
Los proyectos que "codifican todo" tienen un recuento de módulos mucho mayor y se vuelven difíciles de manejar e inflexibles.
fuente