
Hace algún tiempo, el creador del lenguaje de programación Lua, Roberto Ierusalimschy, visitó nuestra oficina de Moscú. Le hicimos algunas preguntas que preparamos con la participación de los usuarios de Habr.com también. Y finalmente, nos gustaría compartir la versión de texto completo de esta entrevista.
- Comencemos con algunos asuntos filosóficos. Imagínese, si recreara a Lua desde cero, ¿qué tres cosas cambiaría en Lua?- Wow! Esa es una pregunta difícil. Hay tanta historia incrustada en la creación y desarrollo del lenguaje. No fue como una gran decisión a la vez. Hay algunos remordimientos, varios de los cuales tuve la oportunidad de corregir a lo largo de los años. La gente se queja de eso todo el tiempo debido a la compatibilidad. Lo hicimos varias veces. Solo estoy pensando en cosas pequeñas.
- ¿Global por defecto? ¿Crees que este es el camino?- tal vez. Pero es muy difícil para los lenguajes dinámicos. Tal vez la solución sea no tener ningún valor predeterminado, pero sería difícil usar variables entonces.
Por ejemplo, tendría que declarar de alguna manera todas las bibliotecas estándar. Desea una línea,
print(sin(x))
, y luego tendrá que declarar 'print' y también declarar 'sin'. Por lo tanto, es un poco extraño tener declaraciones para ese tipo de scripts muy cortos.
Cualquier cosa más grande no debería tener valores predeterminados, creo. Local por defecto no es la solución, no existe. Es solo para tareas, no para uso. Algo que asignamos, y luego usamos y luego asignamos, y hay algún error, completamente desconcertante.
Quizás global por defecto no es perfecto, pero seguro que local por defecto no es una solución. Creo que algún tipo de declaración, tal vez una declaración opcional ... Hemos tenido esta propuesta muchas veces, algún tipo de declaración global. Pero al final, creo que el problema es que la gente comienza a pedir más y más y nos damos por vencidos.
(sarcásticamente) Sí, vamos a hacer una declaración global: agregue eso y eso y eso, publíquelo, y al final entendemos que la conclusión final no satisfará a la mayoría de las personas y no pondremos todas las opciones que todos quieren, entonces no ponemos nada. Al final, el modo estricto es un compromiso razonable.
Existe este problema: por lo general, usamos campos dentro de los módulos, por ejemplo, entonces tiene los mismos problemas nuevamente. Es solo un caso muy específico de errores que la solución general probablemente debería incluir. Así que creo que si realmente quieres eso, debes usar un lenguaje estáticamente escrito.
- Global por defecto también es bueno para archivos de configuración pequeños.- Sí, exactamente, para pequeños guiones, etc.
- No hay compensaciones aquí?- No, siempre hay compensaciones. Existe una compensación entre pequeños scripts y programas reales o algo así.
- Entonces, volvemos a la primera gran pregunta: tres cosas que cambiarías si tuvieras la oportunidad. Desde mi punto de vista, estás bastante contento con lo que tenemos ahora, ¿verdad?- Bueno, no es un gran cambio, pero aún así ... Nuestra deuda incobrable que se convirtió en un gran cambio es nula en las tablas. Es algo de lo que realmente me arrepiento. Hice ese tipo de implementación, una especie de pirateo ... ¿Viste lo que hice? Envié una versión de Lua hace unos seis meses o un año que tenía nulos en las tablas.
- ¿Valores nulos?- Exactamente Creo que se llamaba nils en las tablas, lo que se llama nulo. Hicimos un truco en la gramática para que sea algo compatible.
- ¿Por qué es necesario?- Estoy realmente convencido de que este es un problema completo de agujeros ... Creo que la mayoría de los problemas de nils en las matrices desaparecerían si pudiéramos tener [nils en las tablas] ... Porque el problema exacto no es nils en las matrices. La gente dice que no podemos tener nils en las matrices, por lo que deberíamos tener matrices separadas de las tablas. ¡Pero el verdadero problema es que no podemos tener nils en las tablas! Entonces, el problema está en las tablas, no en la forma en que representamos las matrices. Si pudiéramos tener nils en tablas, entonces tendríamos nils en matrices sin otra cosa. Así que esto es algo de lo que realmente me arrepiento, y muchas personas no entienden cómo cambiarían las cosas si Lua permitiera nulos en las tablas.
- ¿Puedo contarte una historia sobre Tarantool? De hecho, tenemos nuestra propia implementación de nulo, que es un CDATA a un puntero nulo. Lo usamos donde se requieren huecos en la memoria. Para completar argumentos posicionales cuando hacemos llamadas remotas, etc. Pero generalmente sufrimos porque CDATA siempre se convierte en 'verdadero'. Entonces nils en matrices resolvería muchos de nuestros problemas.- Si, lo se. Ese es exactamente mi punto: esto resolvería muchos problemas para muchas personas, pero hay un gran problema de compatibilidad. No tenemos la energía para lanzar una versión que sea tan incompatible y luego romper la comunidad y tener documentación diferente para Lua 5 y Lua 6, etc. Pero tal vez algún día lo lanzaremos. Pero es un cambio realmente grande. Creo que debería haber sido así desde el principio; si lo fuera, sería un cambio trivial en el idioma, excepto por la compatibilidad. Rompe muchos programas, de maneras muy sutiles.
- ¿Cuáles son las desventajas, excepto la compatibilidad?- Además de la compatibilidad, la desventaja es que necesitaríamos dos nuevas operaciones, dos nuevas funciones. Al igual que 'eliminar clave', porque asignar nil no eliminaría la clave, por lo que tendríamos una especie de operación primitiva para eliminar la clave y realmente eliminarla de la tabla. Y 'prueba' para verificar dónde exactamente distinguir entre nulo y ausente. Entonces necesitamos dos funciones primitivas.
- ¿Ha analizado el impacto de esto en implementaciones reales?- Sí, lanzamos una versión de Lua con eso. Y como dije, rompe el código de muchas maneras sutiles. Hay personas que hacen table.insert (f (x)): una llamada a una función. Y es a propósito, es por diseño que cuando una función no quiere insertar nada, devuelve nil. Entonces, en lugar de una marca de verificación "¿quiero insertar?", Entonces llamo a table.insert, y sabiendo que si es nulo, no se insertará. Como todo en cada idioma, un error se convierte en una característica, y las personas usan la característica, pero si la cambia, se rompe el código.
- ¿Qué pasa con un nuevo tipo de vacío? Como nulo, pero vacío?- Oh no, esto es una pesadilla. Simplemente pospones el problema, si pones otro, entonces necesitas otro y otro y otro. Esa no es la solución. El problema principal, bueno, no principal, pero uno de los problemas, es que nulo ya está arraigado en muchos lugares del idioma. Por ejemplo, un ejemplo muy típico. Decimos: debe evitar nulos en matrices, agujeros. Pero luego tenemos funciones que devuelven nil y algo después de nil, por lo que obtenemos un código de error. De modo que la construcción en sí asume lo que representa nil ... Por ejemplo, si quiero hacer una lista de los retornos de esa función, solo para capturar todos estos retornos.
- Por eso tienes un truco para eso. :)- Exactamente, pero no tienes que usar hacks para un [problema] tan primitivo y obvio. Pero la forma en que se construyen las bibliotecas ... Una vez pensé en eso, tal vez las bibliotecas deberían devolver falso en lugar de cero, pero es una solución a medio cocinar, resuelve solo una pequeña parte del problema. El verdadero problema, como dije, es que deberíamos tener nils en las tablas. Si no, tal vez no deberíamos usar nils con tanta frecuencia como lo hacemos ahora. Todo es un poco desordenado. Por lo tanto, si crea un vacío, estas funciones aún devolverían un valor nulo, y todavía tendríamos este problema a menos que creáramos un nuevo tipo y las funciones devolvieran el valor vacío en lugar de nulo.
- Void podría usarse para decir explícitamente que la clave debe mantenerse en una tabla - clave con un valor de vacío. Y nada puede actuar como antes.- Sí, a eso me refiero. Todas las funciones en las bibliotecas deben devolver void o nil.
- Todavía pueden regresar nulo, ¿por qué no?- Porque todavía tendríamos el problema de que no puedes capturar algunas funciones.
- Pero no habrá una primera clave, solo una segunda clave.- No, no habrá una segunda clave, porque el conteo será incorrecto y tendrás un agujero en la matriz.
- Sí, ¿estás diciendo que necesitas un metametodo falso?- si. Mi sueño es algo así:
{f(x)}
Debe capturar todos los retornos de la función
f(x)
. Y luego puedo hacer
%x
o
#x
, y eso me dará el número de retornos de la función. Eso es lo que debe hacer un lenguaje razonable. Por lo tanto, crear un vacío no resolverá eso, a menos que tengamos una regla muy fuerte de que las funciones nunca deberían devolver nil, pero entonces ¿por qué necesitamos nil? Quizás deberíamos evitarlo.
- Roberto, ¿habrá un soporte de análisis estático mucho más fuerte para Lua? Como "Lua Check en esteroides". Sé que no resolverá todos los problemas, por supuesto. Estás diciendo que esta es una característica para 6.0, si alguna vez, ¿verdad? Entonces, si en un 5.x habrá una herramienta de análisis estático fuerte, si se invirtieran horas-hombre y años-hombre, ¿realmente ayudaría?- No, creo que una herramienta de análisis estático realmente fuerte se llama ... ¡sistema de tipos! Si desea una herramienta realmente sólida, debe usar un lenguaje de tipo estático, algo como Haskell o incluso algo con tipos dependientes. Entonces tendrás herramientas de análisis realmente fuertes.
- Pero entonces no tienes a Lua.- Exactamente, Lua es para ...
- Impreciso? Realmente disfruté tu foto de jirafa en tipos estáticos y dinámicos.- Sí, mi última diapositiva.
La última diapositiva de la charla de Roberto Ierusalimschy "¿Por qué (y por qué no) Lua?"
en la conferencia de Lua en Moscú 2019- Para nuestra próxima pregunta preparada, volvamos a esa imagen. Si lo entendí bien, su posición es que Lua es una pequeña herramienta útil para resolver tareas no muy grandes.- No, creo que puedes hacer algunas tareas grandes, pero no con análisis estático. Creo firmemente en las pruebas. Por cierto, no estoy de acuerdo con usted en la cobertura, su opinión es que no debemos perseguir la cobertura ... Quiero decir, estoy totalmente de acuerdo en que la cobertura no implica una prueba completa, pero la no cobertura implica una prueba de cero por ciento. Así que di una charla sobre una sala de pruebas: estabas allí en Estocolmo. Así que comencé mi prueba con [algunos] errores, eso es lo más extraño, uno de ellos era famoso, el otro era completamente no famoso. Es algo completamente roto en un archivo de encabezado de Microsoft, C y C ++. Así que busco en la web y a nadie le importa ni lo notó.
Por ejemplo, hay una función matemática,
modf () , donde tienes que pasar un puntero a un doble porque devuelve dos dobles. Traducimos la parte entera del número o la parte fraccionaria. Así que esto es parte de una biblioteca estándar desde hace mucho tiempo. Luego vino C 99, y necesita esta función para flotadores. Y el archivo de encabezado de Microsoft simplemente mantuvo esta función y declaró otra como macro. Así que se convirtió en este tipo de moldes. Entonces arrojó el doble para flotar, ok, ¡y luego arrojó el puntero al doble para que el puntero flote!
- Algo está mal en esta imagen.- Este es un archivo de encabezado de Visual C ++ y Visual C 2007. Quiero decir, si llamó a esta función una vez, con algún parámetro y comprobó los resultados, sería incorrecto a menos que sea cero. De lo contrario, cualquier otro valor será incorrecto. Nunca usarías esta función. Cero cobertura. Y luego hay muchas discusiones sobre las pruebas ... Quiero decir, solo llame a una función una vez, ¡verifique los resultados! Entonces está allí, ha estado allí durante mucho tiempo, durante muchos años a nadie le importó. Uno muy famoso fue en Apple.
Algo así como "
if… what… goto… ok
", era algo así. Alguien puso otra declaración aquí. Y entonces todo iba a ir bien. Y hubo muchas discusiones sobre que debería tener las reglas, los corchetes deberían ser obligatorios en su estilo, etc., etc. Nadie mencionó que hay muchos otros ifs aquí. Eso nunca ha sido ejecutado ...
- También hay un problema de seguridad por lo que recuerdo.Sí, exactamente. Porque solo estaban probando casos aprobados. No estaban probando nada, porque todo sería aprobado. Significa que no hay un solo caso de prueba en la aplicación de seguridad que verifique si rechaza alguna conexión o lo que sea que deba rechazar. Entonces todos discuten y dicen que deberían tener paréntesis ... ¡Deben tener exámenes, exámenes mínimos! Como nadie ha probado eso, a eso me refiero con cobertura. Es increíble cómo la gente no hace pruebas básicas. Porque si estaban haciendo todas las pruebas básicas, entonces, por supuesto, es una pesadilla hacer toda la cobertura y ejecutar todas las líneas, etc. La gente descuida incluso las pruebas básicas, por lo que la cobertura es al menos aproximadamente la mínima. Es una forma de llamar la atención sobre algunas partes del programa que olvidó. Es una especie de guía sobre cómo mejorar un poco sus pruebas.
- ¿Qué es la cobertura de prueba en Tarantool? 83%! Roberto, ¿cuál es la cobertura de prueba de Lua?- Alrededor de 99.6. ¿Cuántas líneas de código tienes? ¿Un millón, cientos de miles? Estos son grandes números. El uno por ciento de cien mil son mil líneas de código que nunca se probaron. No lo ejecutaste en absoluto. Sus usuarios no prueban nada.
- Entonces, ¿hay un 17 por ciento de las características de Tarantool que no se usan actualmente?- No estoy seguro de querer desapilar todo de nuevo a donde estábamos ... Creo que uno de los problemas con los lenguajes dinámicos (y los estáticos) es que la gente no prueba cosas. Incluso si tienes un lenguaje estático, a menos que tengas algo, ni siquiera como Haskell, sino Coq, algún sistema de prueba, lo cambias por eso o aquello. Ninguna herramienta de análisis estático puede detectar estos errores, por lo que necesita pruebas. Y si tiene las pruebas, detecta problemas globales, cambia el nombre de los errores ortográficos, etc. Todo este tipo de errores. De todos modos, debe hacerse estas pruebas, tal vez a veces sea un poco más difícil de depurar, a veces no lo es, depende del idioma y el tipo de error. Pero el problema es que ninguna herramienta de análisis estático puede permitirle evitar pruebas. Las pruebas, por otro lado ... bueno, nunca prueban la ausencia de error, pero me siento mucho más seguro después de todas las pruebas.
- Tenemos una pregunta sobre cómo probar los módulos Lua. Como desarrollador, quiero probar algunas funciones locales que pueden usarse más adelante. La pregunta es: queremos tener una cobertura de aproximadamente el 99 por ciento, pero para la API que produce este módulo, el número de casos funcionales que debería producir es mucho menor que la funcionalidad que admite internamente.- ¿Por qué es eso, lo siento?
- Hay alguna funcionalidad que no es accesible por la interfaz pública.- Si hay una funcionalidad a la que la interfaz pública no puede acceder, no debería estar allí, simplemente bórrela. Borra ese código.
- ¿Solo matarlo?- Sí, a veces hago eso en Lua. Hubo cierta cobertura de código, no pude llegar allí o allí o allá, así que pensé que era imposible y simplemente eliminé el código. No es tan común, pero sucedió más de una vez. Esos casos fueron imposibles de suceder, simplemente pones una afirmación para comentar por qué no puede suceder. Si no puede acceder a sus funciones desde la API pública, no debería estar allí. Deberíamos codificar la API pública con una entrada incorrecta, eso es esencial para las pruebas.
- Eliminar código, la eliminación es buena, reduce la complejidad. La complejidad reducida aumenta la mantenibilidad y la estabilidad. Mantenlo simple.- Sí, la programación extrema tenía esta regla. Si no está en una prueba, entonces no existe.
- ¿Qué idiomas te inspiraron cuando creaste Lua? ¿Qué paradigmas o especialidades funcionales o partes de estos lenguajes te gustaron?- Diseñé Lua para un propósito muy específico, no era un proyecto académico. Es por eso que cuando me preguntas si volvería a crearlo, te digo que hay muchas cosas históricas en el idioma. No comencé con 'Permítanme crear el lenguaje que quiero o quiero usar o que todos necesitan, etc. Mi problema era 'Este programa aquí necesita un lenguaje de configuración para geólogos e ingenieros, y necesito crear un lenguaje pequeño que puedan usar con una interfaz fácil. Es por eso que la API siempre fue una parte integral del lenguaje, porque es más fácil de integrar. Ese era el objetivo. Lo que tenía en mi fondo, son muchos idiomas diferentes en ese momento ... alrededor de diez. Si quieres todo el fondo ...
- Me interesaban los idiomas que querías incluir en Lua.- Estaba obteniendo cosas de muchos idiomas diferentes, cualquiera que fuera el problema que tenía. La mayor inspiración fue el lenguaje Modula para la sintaxis, pero de lo contrario, es difícil de decir porque hay muchos idiomas. Algunas cosas vinieron de AWK, fue otra pequeña inspiración. Por supuesto, Scheme y Lisp ... Siempre estuve fascinado con Lisp desde que comencé a programar.
- Y todavía no hay macros en Lua!- Sí, hay mucha diferencia en la sintaxis. Fortran, creo, fue el primer idioma ... no, el primer idioma que aprendí fue la Asamblea, luego vino Fortran. Estudié, pero nunca usé CLU. Hice mucha programación con Smalltalk, SNOBOL. También estudié, pero nunca usé Icon, también es muy interesante. Mucho vino de Pascal y C. Cuando creé Lua, C ++ ya era demasiado complejo para mí, y eso fue antes de las plantillas, etc. Era 1991, y en 1993 se inició Lua.
- La Unión Soviética cayó y comenzaste a crear Lua. :) ¿Estabas aburrido con punto y coma y objetos cuando comenzaste a trabajar en Lua? Esperaría que Lua tuviera una sintaxis similar a C, porque está integrada a C. Pero ...- Sí, creo que es una buena razón para no tener una sintaxis similar, por lo que no se mezclan, estos son dos idiomas diferentes.
Es algo realmente divertido y está conectado a la respuesta que no me permitiste [en la conferencia] dar en matrices a partir de 1. Mi respuesta fue demasiado larga.
Cuando comenzamos Lua, el mundo era diferente, no todo era como C. Java y JavaScript no existían, Python estaba en una infancia y tenía una versión inferior a la 1.0. Así que no había esta cosa cuando se supone que todos los lenguajes son C-like. C era solo una de las muchas sintaxis.
Y las matrices eran exactamente las mismas. Es muy divertido que la mayoría de la gente no se dé cuenta de eso. Hay cosas buenas sobre las matrices basadas en cero, así como las matrices basadas en uno.
El hecho es que los lenguajes más populares hoy en día son de base cero debido a C. Fueron inspirados por C. Y lo curioso es que C no tiene indexación. Por lo tanto, no puede decir que C indexa las matrices desde cero, porque no hay operación de indexación. C tiene aritmética de puntero, por lo que cero en C no es un índice, es un desplazamiento. Y como compensación, debe ser un cero, no porque tenga mejores propiedades matemáticas o porque sea más natural, lo que sea.
Y todos esos lenguajes que copiaron C, tienen índices y no tienen aritmética de puntero. Java, JavaScript, etc., etc. - ninguno de ellos tiene aritmética de puntero. Entonces simplemente copiaron el cero, pero es una operación completamente diferente. Ponen cero sin razón alguna: es como un culto de carga.
- Estás diciendo que es lógico si tienes un lenguaje incrustado en C para hacerlo con una sintaxis tipo C. Pero si tiene un lenguaje incrustado en C, supongo que tiene programadores en C que desean que el código esté en C y no en otro lenguaje, que se parece a C, pero no es C. Por lo tanto, se suponía que los usuarios de Lua nunca debían usar C diariamente? Por qué- ¿Quién usa C todos los días?
- Programadores de sistemas.- Exactamente Ese es el problema, demasiadas personas usan C, pero no se les debe permitir usarlo. Los programadores deben estar certificados para usar C. ¿Por qué el software está tan dañado? Todos esos hacks que invaden el mundo, todos esos problemas de seguridad. Al menos la mitad de ellos se debe a C. Es realmente difícil programar en C.
- Pero Lua está en C.- Sí, y así es como aprendimos lo difícil que es programar en C. Tiene desbordamientos de búfer, desbordamientos de enteros que causan desbordamientos de búfer ... Solo obtenga un solo programa C que pueda estar seguro de que no aritmética falla si la gente pone cualquier número en cualquier lugar y todo está marcado. Por otra parte, los problemas de portabilidad real, tal vez a veces en una CPU funciona, pero luego llega a la otra CPU ... Es una locura.
Por ejemplo, muy recientemente tuvimos un problema. ¿Cómo sabes que tu programa C no hace desbordamiento de pila? Me refiero a la profundidad de la pila, no al desbordamiento de la pila porque invadiste ... ¿Cuántas llamadas tienes derecho a hacer en un programa en C?
- Depende del tamaño de una pila.- Exactamente ¿Qué dice la norma sobre eso? Si codifica en C y luego hace esta función que llama a esta función que llama a esta función ... ¿cuántas llamadas puede hacer?
- 16 mil?- Puedo estar equivocado, pero creo que el estándar no dice nada al respecto.
- Creo que no hay nada en el estándar porque depende demasiado del tamaño.- Por supuesto, depende del tamaño de cada función. Puede ser enormes matrices automáticas en el marco de la función ... Por lo tanto, el estándar no dice nada y no hay forma de verificar si una llamada será válida. Por lo tanto, puede tener un solo problema si tiene tres pasos de llamada, puede bloquearse y seguir siendo un programa válido de C. Correcto de acuerdo con el estándar, aunque no es correcto porque se bloquea. Entonces es muy difícil programar en C, porque hay tantos ... Otro buen ejemplo: ¿cuál es el resultado cuando resta dos punteros? ¿Nadie aquí trabaja con C?
- No, así que no los ases a la parrilla. Pero C ++ admite diferentes tipos.- No, C ++ tiene el mismo problema.
- ¿Cuál es el tipo de declaración? ptrdiff_t
?- Exactamente,
ptrdiff_t
es un tipo con signo. Por lo general, si tiene una memoria estándar del tamaño de su palabra y resta dos punteros en este espacio, no puede representar todos los tamaños en el tipo con signo. Entonces, ¿qué dice el estándar sobre eso?
Cuando resta dos punteros, si la respuesta cabe en un puntero diff, entonces esa es la respuesta. De lo contrario, tiene un comportamiento indefinido. ¿Y cómo sabes si te queda bien? Usted no Entonces, cada vez que restas dos punteros, generalmente sabes que eso está fuera del estándar, que si estás apuntando a algo más grande que al menos 2 bytes, entonces el tamaño más grande sería la mitad del tamaño de la memoria, así que todo está bien.
Entonces, solo tiene un problema si apunta a bytes o caracteres. Pero cuando haces eso, tienes un problema real, no puedes hacer aritmética de puntero sin preocuparte de que tengas una cadena más grande que la mitad de la memoria. Y luego no puedo calcular el tamaño y almacenarlo en un tipo de diferencia de puntero porque está mal.
A eso me refiero con tener un programa seguro de C o C ++ que sea realmente seguro.
- ¿Has considerado implementar Lua en un idioma diferente? ¿Cambiarlo de C a otra cosa?- Cuando comenzamos, consideré C ++, pero como dije, dejé de usarlo debido a la complejidad: no puedo aprender todo el lenguaje. Debería ser útil tener algunas cosas de C ++ pero ... incluso hoy no veo ningún lenguaje que funcione.
- ¿Puedes explicar por qué?- Porque no tengo alternativas. Solo puedo explicar por qué contra otros idiomas. No digo que C sea perfecto o incluso bueno, pero es lo mejor. Para explicar por qué, necesito compararlo con otros idiomas.
- ¿Qué hay de JVM?- Oh, JVM. Vamos, no cabe en la mitad del hardware ... La portabilidad es la razón principal, pero también el rendimiento. En JVM es un poco mejor que .NET, pero no es tan diferente. Lua hace muchas cosas que no podemos hacer con JVM. No puede controlar el recolector de basura, por ejemplo. Debe usar el recolector de basura JVM porque no puede tener un recolector de basura diferente implementado sobre JVM. JVM también es un gran consumidor de memoria. Cuando cualquier programa Java comienza a saludar, es como 10 MB más o menos. La portabilidad es un problema no porque no se haya portado, sino porque no se puede portar.
- ¿Qué pasa con las modificaciones de JVM como Mobile JVM?- Eso no es JVM, es una broma. Es como una micro edición de Java, no Java.
- ¿Qué tal otros lenguajes estáticos como Go o Oberon? ¿Podrían ser la base de Lua si lo creaste hoy?- Oberon ... podría ser, depende ... Ve, de nuevo, tiene un recolector de basura y tiene un tiempo de ejecución demasiado grande para Lua. Oberon sería una opción, pero Oberon tiene algunas cosas muy extrañas, como que casi no tienes constantes, si no recuerdo mal. Sí, creo que eliminaron a Const de Pascal a Oberon. Tenía un libro sobre Oberón y amaba a Oberón. Su
sistema era increíble, es realmente algo.
Recuerdo que en 1994 vi una demostración de Oberon y Self. ¿Te conoces? Es un lenguaje dinámico muy interesante con compiladores de jit, etc. Vi estas demostraciones con una semana de diferencia, y Self fue muy inteligente, utilizaron algunas técnicas de dibujos animados para disfrazar la lentitud de las operaciones. Porque cuando abriste algo, fue como '¡woop!' - Primero se reduce un poco, luego se expande con algunos efectos. Fue implementado muy bien, estas técnicas las usaron para simular movimiento ...
Luego, una semana después, vimos una demostración de Oberon, se estaba ejecutando como 1/10 de hardware para Self: había una máquina pequeña muy antigua. En Oberon haces clic y luego solo boom, todo funciona de inmediato, todo el sistema era muy ligero.
Pero para mí es demasiado minimalista, eliminaron constantes y tipos de variantes.
- Haskell?- No sé Haskell o cómo implementar Lua en Haskell.
- ¿Y cuál es su actitud hacia lenguajes como Python o R o Julia como base para futuras implementaciones de Lua?- Creo que cada uno de estos tiene sus usos.
R parece ser bueno para las estadísticas. Es muy específico del dominio, hecho por personas en el área, por lo que esta es una fortaleza.
Python es bueno, pero tuve problemas personales con él. Pensé que lo mencioné en mi charla o en la entrevista. Eso de no saber todo el idioma o no usarlo, la falacia del subconjunto.
Usamos Python en nuestros cursos, enseñando programación básica, solo una pequeña parte, loops y enteros. Todos estaban contentos, y luego dijeron que sería bueno tener algunas aplicaciones gráficas, por lo que necesitábamos alguna biblioteca gráfica. Y casi todas las bibliotecas gráficas, obtienes la API ... Pero no conozco Python lo suficiente, esto es algo muy avanzado. Tiene la ilusión de que es fácil y tengo todas estas bibliotecas para todo, pero es fácil o tienes todo.
Entonces, cuando comienzas a usar el lenguaje, comienzas: oh, tengo que aprender OOP, herencia, cualquier otra cosa. Cada biblioteca individual. Parece que los autores se enorgullecen de usar funciones de lenguaje más avanzadas en su API para mostrar que no sé qué. Llamadas a funciones, tipos estándar, etc. Tienes este objeto, y luego, si quieres otra cosa, debes crear otro objeto ...
Incluso la coincidencia de patrones, puede hacer algunas cosas simples, pero generalmente la coincidencia de patrones estándar no es algo que haga. Haces una coincidencia, un objeto devuelve un resultado y luego llamas a métodos sobre el resultado de ese objeto para obtener el resultado real de la coincidencia. A veces hay una forma más simple de usar, pero no es obvio, no es la forma en que la mayoría de la gente lo usa.
Otro ejemplo: estaba enseñando un curso sobre coincidencia de patrones y quería usar una sintaxis similar a Perl, y no podía usar Lua debido a una sintaxis completamente diferente. Entonces pensé que Python sería el ejemplo perfecto. Pero en Python hay algunas funciones directas para algunas cosas básicas, pero para cualquier cosa más compleja tendrías que conocer objetos y métodos, etc. Solo quería hacer algo y tener el resultado.
- ¿Qué terminaste usando?- Usé Python y les expliqué. Pero incluso Perl es mucho más simple, haces la combinación y los resultados son $ 1, $ 2, $ 3, es mucho más fácil, pero no tengo el coraje de usar Perl, así que ...
- Estuve usando Python durante dos años antes de notar que había decoradores. (pregunta de Yaroslav Dynnikov del equipo de Tarantool)- Sí, y cuando quieres usar una biblioteca, tienes que aprender estas cosas y no entiendes API, etc. Python da la ilusión de que es fácil pero es bastante complejo.
... Y Julia, no sé mucho sobre Julia, pero me recordó a LuaJIT en el sentido de que a veces parece orgullo del usuario. Puede obtener muy buenos resultados, pero debe comprender realmente lo que está sucediendo. No es como escribir código y obtener buenos resultados. No, escribes código y a veces los resultados son buenos, a veces son horribles. Y cuando los resultados son horribles, tiene muchas herramientas buenas que le muestran el lenguaje intermedio que una vez se generó, lo verifica y luego pasa por todo este código casi ensamblado. Entonces te das cuenta: oh, no está optimizando eso por eso. Ese es el problema de los programadores, les gustan los juegos y a veces les gustan las cosas porque es difícil, no porque sea fácil.
No sé mucho sobre Julia, pero una vez vi una conversación al respecto. Y el tipo que hablaba era el que tenía este punto de vista: mira qué bueno es, escribimos este programa y es perfecto. No recuerdo mucho, algo sobre la multiplicación de matrices, supongo. Y luego los flotadores son perfectos, luego los dobles son perfectos, y luego ponen números complejos ... y fue una tragedia. Como cien veces más lento.
(sarcásticamente) 'Mira lo bueno que es, tenemos esta herramienta, podemos ver todo el ensamblaje [listado], y luego vas y cambias eso y eso y eso. Vea cuán eficiente es esto '. Sí, ya veo, puedo programar en conjunto directamente.
Pero eso fue solo una charla. Estudié un poco de R y tengo algo de experiencia de usuario con Python para cosas pequeñas.
- ¿Qué opinas de Erlang?- Erlang es un lenguaje divertido. Tiene algunos usos realmente buenos, la tolerancia a fallas es realmente interesante. Pero afirman que es un lenguaje funcional y la idea del lenguaje funcional es que no tienes un estado.
Y Erlang tiene un enorme estado oculto en los mensajes que se envían y aún no se reciben. Por lo tanto, cada pequeño proceso es completamente funcional, pero el programa en sí es completamente no funcional.
Es un desastre de datos ocultos que es mucho peor que las variables globales porque si fueran variables globales, las imprimirías. Mensajes que son el estado real de su sistema. En cada momento, ¿cuál es el estado del sistema? Hay todos estos mensajes enviados aquí y allá. Es completamente no funcional, en absoluto.
- Entonces Erlang miente sobre ser funcional y Python miente sobre ser simple. ¿Sobre qué miente Lua?- Lua miente un poco acerca de ser pequeña. Todavía es más pequeño que la mayoría de los otros idiomas, pero si quieres un idioma realmente pequeño, entonces Lua es más grande de lo que quieres que sea.
- Entonces, ¿qué es un idioma pequeño?- Forth es, amo a Forth.
- ¿Hay espacio para una versión más pequeña de Lua?- Quizás, pero es difícil. Me encantan las mesas pero las mesas no son muy pequeñas. Si desea representar cosas pequeñas, la idea detrás de las mesas no le conviene. Sería una sintaxis de Lua, lo llamaríamos Lua pero no es Lua.
Sería como la micro edición de Java. Lo llamas Java pero ¿tiene subprocesos múltiples? No lo hace ¿Tiene un reflejo? No lo hace Entonces, ¿por qué usarlo? Tiene una sintaxis de Java, el mismo sistema de tipos, pero no es Java en absoluto. Es un lenguaje diferente que es más fácil de aprender si conoce Java pero no es Java.
Si desea hacer un lenguaje pequeño que se parezca a Lua pero Lua sin tablas no es ... Probablemente debería tener que declarar tablas, algo así como FFI para poder ser pequeño.
- ¿Hay adaptaciones más pequeñas de Lua?- Quizás no lo sé.
- ¿Está Lua listo para la programación funcional pura? ¿Puedes hacerlo con Lua?- Por supuesto que puedes. No es particularmente eficiente, pero solo Haskell es realmente eficiente para eso. Si comienza a usar mónadas y cosas por el estilo, crea nuevas funciones, compone funciones, etc.
— Actually, there is a library for functional programming in Lua.— Yes, it's reasonable and usable, if you do really need performance; you can do a lot of stuff with it. I love functional stuff and I do it all the time.
— My question is more about the garbage collector, because we only have only mutable objects and we have to use them efficiently. Will Lua be good for that?— I think a new incarnation of garbage collector will help a lot, but again…
— Young die young? The one that seems to work with young objects?— Exactly, yes. But as I said even with the standard garbage collector we don't have optimal performance but it can be reasonable. More often you don't even need that performance for most actions unless you are writing servers and having big operations.
— What functional programming tasks do you perform in Lua?— A simple example. My book, I'm writing my own format and I have a formatter that transforms that in LaTex or DocBook. It's completely functional, it has a big pattern matching… It's slightly inspired by LaTex but much more uniformed. There's @ symbol instead of backslash, a name of a macro and one single argument in curly brackets. So I have gsub that recognizes this kind of stuff and then it calls a function, the function does something and returns something. It's all functional, just functions on top of functions on top of functions, and the final function gives a big result.
— Why don't you program with LaTeX?— Plain LaTeX? First, it's too tricky for a lot of stuff and so difficult. I have several things that I don't know how to do in LaTex. For example, I want to put a piece of inline code inside a text. Then there is a slash verb, standard stuff. But slash verb gives fixed space. And the space between stuff is never right. All real spaces are variable, it depends on how the line is adjusted, so it expands in some spaces and compacts in others depending on a lot of stuff. And those spaces are fixed, so sometimes they look too large, sometimes too small. It also depends on what you put in code.
— But you still render your own format to LaTeX?— Yes, but with a lot of preprocessing. I write my own verb but then it changes and becomes not a verb but a lot of stuff. For example, when I write 3+1 I write a very small space here. In verb, if I don't put any space here, it shrinks, and if I do, it's too large. So I do the preprocessing, inserting a variable space. It's very small but can be a little larger if it needs to adjust. But if I put 'and' after 1 then I put a larger space. This function here does all that. This is a small example but there are other things…
— Do you have a source?— I do have the source, it is in the
git . The program's called
2html . The current version only generates HTML… Sorry, that's a kind of a mess. I created it for a book but also another one for the manual. The one in the git is for the manual. But the other one is more complicated and not public, I can't make it public. But the main problem is that TeX is not there. It's almost impossible to process TeX files without TeX itself.
— Is it not machine-readable?— Yes, it's not machine-readable. I mean, it is readable because TeX reads it. It's so hard to test, so many strange rules etc. So this is much more uniformed and as I said I generate DocBook format, sometimes I need it. That started when I had this contract for a book.
— So you use 2html to generate DocBook?— Yes, it generates DocBook directly.
— Ok, thank you very much for the interview!
If you have any more questions, you can ask them in the
Lua Mailing List . See you soon!