Lua em Moscou 2019: entrevista com Roberto Jerusalem



Há algum tempo, Roberto de Jerusalém, autor da língua Lua, visitou nosso escritório em Moscou. Nós o entrevistamos, durante o qual fizemos perguntas aos leitores da Habr. Por fim, podemos compartilhar com você toda a gravação da conversa.

- Vamos filosofar para começar. Se você fosse construir Lua novamente do zero, que três coisas você mudaria nesse idioma?

Uau! Pergunta difícil. Há toda uma história por trás da criação e desenvolvimento da linguagem. Esta não foi uma grande decisão. Houve decisões das quais me arrependi e que ao longo dos anos fui capaz de corrigir. E os programadores reclamam disso o tempo todo porque a compatibilidade está quebrada. Fizemos isso várias vezes. E penso apenas em algumas pequenas tarefas.

- Padrões globais (Global por padrão)? Você acha que esse é o caminho certo?

Talvez. Mas esse caminho é muito difícil para linguagens dinâmicas. Talvez você deva abandonar completamente o conceito de "padrão", mas será difícil usar variáveis.
Por exemplo, você precisa declarar de alguma forma todas as bibliotecas padrão. Você precisa de one-liner , print(sin(x)) e depois declarar "print" e outro "sin". É estranho ter anúncios para scripts tão curtos.

Qualquer coisa maior não deve ter nada por padrão, como me parece. Local por padrão não é uma solução, nem sequer existe. É apenas para atribuição, não para uso. Atribuímos algo, usamos e atribuímos novamente, e ocorre um erro completamente inexplicável.

Talvez a globalidade padrão não seja perfeita, mas a localidade padrão definitivamente não é uma opção. Eu acho que algum tipo de anúncio, talvez opcional ... Pretendemos muitas vezes fazer algum tipo de anúncio global. Mas se apresentarmos cegamente tudo o que for solicitado, nada de bom resultará disso.

(sarcasticamente) Sim, vamos apresentar um anúncio global, acrescentar que, sho, quinto, décimo, retirar outro e, como resultado, percebemos que a solução final não satisfaz a maioria dos programadores e não adicionaremos todos os recursos solicitados e, portanto, nós não implementamos nada. Afinal, o modo estrito é um compromisso razoável.

Há um problema: na maioria das vezes usamos, por exemplo, os campos dentro dos módulos e, novamente, você tem os mesmos problemas. Este é apenas um caso muito específico de erros, que provavelmente deve ser levado em consideração na solução geral. Portanto, se você realmente precisar, é melhor usar uma linguagem de tipo estaticamente.

- A globalidade padrão ainda é conveniente para pequenos arquivos de configuração.

"Sim, Ă© verdade, para pequenos scripts e afins."

- E sem compromissos neste caso?

- Sempre há compromissos. Nesse caso, um compromisso entre pequenos scripts e programas reais, algo assim.

- E aqui voltamos à primeira grande questão: que três coisas você mudaria se houvesse essa oportunidade? Parece-me que você está muito feliz com o estado atual das coisas, certo?

- Bem, eu não diria que é uma grande mudança, e ainda ... Uma das decisões malsucedidas que se tornaram uma grande mudança é nula nas tabelas. Me desculpe por isso. Eu fiz esse truque ... Você sabe do que estou falando? Há meio ano ou um ano, lancei uma versão de Lua na qual não havia tabelas.

- Valores nulos?

Exatamente. Eu acho que isso Ă© chamado nulo nas tabelas - ou seja, nulo. Fizemos um truque gramatical para garantir a compatibilidade.

- Por que é necessário?

"Estou realmente convencido de que esse é o problema todo ... acho que a maioria dos problemas com zero nas matrizes desapareceria se pudéssemos ter [zero nas tabelas] ... Mais precisamente, o problema não é com zero nas matrizes". Eles me dizem que matrizes não podem ter nulo, portanto, as matrizes devem ser separadas das tabelas. O verdadeiro problema é que não podemos manter nada nas tabelas! Portanto, o problema não é como representamos matrizes, mas em tabelas. Se pudéssemos ter nada nas tabelas, teríamos nada nas matrizes sem todo o resto. Então, sinto muito por isso, e muitas pessoas não entendem como as coisas poderiam ter mudado se Lua permitisse que nada fosse colocado nas tabelas.

- Posso contar uma história sobre Tarantool? Temos nossa própria implementação de null, que é um CDATA para um ponteiro nulo. Nós o usamos nos casos em que você precisa criar fragmentos vazios em sua memória para inserir argumentos de posicionamento para chamadas remotas e assim por diante. Mas geralmente isso é um problema porque CDATA é sempre convertido em true. E nada em matrizes resolveria muitos problemas.

Sim eu sei. É disso que estou falando - resolveria muitos problemas para muitos, mas isso leva a um problema de compatibilidade ainda maior. Não temos coragem de lançar uma versão que seja tão incompatível e, em seguida, destruir a comunidade e lançar outra documentação para Lua 5, Lua 6, etc. Mas talvez um dia lançaremos essa versão. Essas seriam mudanças muito grandes. Acredito que isso deveria ter sido feito desde o início, e então teríamos conversado sobre uma mudança trivial no idioma, exceto pela compatibilidade. E hoje vai quebrar muitos programas.

- Quais são as deficiências que você vê além do problema de compatibilidade?

- Duas novas funções primitivas serão necessárias. Algo como a "tecla Delete", porque a atribuição de zero não excluirá a chave, portanto, você precisará de uma operação primitiva para realmente removê-la da tabela. E você precisará de um "teste" para verificar exatamente onde há uma diferença entre zero e falta de dados.

- Você analisou o impacto dessas inovações em implementações práticas?

- Sim, lançamos uma versão do Lua. Como eu disse, isso silenciosamente quebrou o código. Alguns usam a chamada de função table.insert(f(x)) . E intencionalmente feito para que, se a função não quiser inserir nada, ela retorne nulo. Então, em vez de uma verificação separada, "Quero incorporar?" Chamo table.insert e, se ficar nulo, sei que ele não será inserido. Como em qualquer outro idioma, o bug se transformou em um recurso e as pessoas o usam. Mas se você alterar o recurso, ele quebrará o código.

- E o tipo de vazio? Como nada, apenas vazio?

"Bem, não, é um pesadelo." Você apenas adia a solução do problema. Se você inserir uma "muleta", precisará de mais uma e mais e mais. Esta não é uma solução. Um dos problemas é que nada já se enraizou em muitos lugares do idioma. Aqui está um exemplo típico: dizemos "evite nada em matrizes, ou seja, buracos". E então escrevemos uma função que retorna nada e nada depois dela, e obtemos um código de erro. Essa construção já implica o que é nulo ... Por exemplo, se eu quiser fazer uma lista dos resultados retornados pela função, apenas para capturar todos eles.

- Para isso vocĂŞ tem um hack :)

"Isso mesmo, mas você não precisa usar hacks para resolver tarefas tão simples e óbvias". No entanto, as bibliotecas fazem isso ... De alguma forma, pensei nisso: talvez as bibliotecas retornem false em vez de nulo, embora essa seja uma opção grosseira, ela resolverá apenas uma pequena parte do problema. O verdadeiro problema, como eu disse, é que precisamos ter nada nas tabelas. Caso contrário, não devemos usar nada com a frequência que penso. Em geral, não está claro. Portanto, se você criou nulo, essas funções ainda retornam nulo, e não resolveremos o problema até criarmos um novo tipo e as funções retornam nulo em vez de nulo.

- Usando void, vocĂŞ pode dizer explicitamente que a chave deve ser armazenada na tabela, a chave com o valor void. E nada pode funcionar como antes.

"Sim, é isso que eu quero dizer." Todas essas funções nas bibliotecas devem retornar nulas ou nulas.

"Eles também podem retornar nulo, por que não?"

- Porque, em alguns casos, não resolveremos o problema da impossibilidade de capturar todos os valores que a função retorna.

"Mas nĂŁo teremos a primeira chave, apenas a segunda."

- Não, não haverá segundo, porque o cálculo será realizado incorretamente e um furo aparecerá na matriz.

- Então você quer dizer que precisa de um metamétodo falso?

Sim. Eu sonho com isso:

{f(x)}

Você precisa interceptar todos os resultados retornados por f(x) . E então eu posso dizer %x ou # %x , e dessa maneira eu sei o número de resultados retornados. É assim que uma linguagem normal deve funcionar. Portanto, criar um vazio não resolverá o problema até que exista uma regra muito rígida que nunca funcione. Mas então por que precisamos de nada? Talvez valha a pena desistir.

- Roberto, haverá um suporte muito mais forte para a análise estática em Lua? Como o Lua Verifique os esteróides? Claro, entendo que isso não resolverá todos os problemas. Você disse que esse recurso aparecerá na versão 6.0, se houver, certo? E se no 5.x houver uma ferramenta poderosa para análise estática - se houver horas-homem investidas nela - isso ajudará?

"Não, acredito que uma ferramenta de análise estática realmente poderosa seja chamada ... um sistema de tipos!" Se você precisar de uma ferramenta realmente poderosa, use uma linguagem de tipo estaticamente como Haskell, ou algum tipo de linguagem com tipos dependentes. Então você definitivamente terá uma poderosa ferramenta de análise.

"Mas entĂŁo eu nĂŁo terei Lua."

- Isso mesmo, Lua é necessária para ...

- Incertezas? Gosto da sua foto com uma girafa sobre tipos estáticos e dinâmicos.

- Sim, este é o meu último slide da apresentação.


O último slide da apresentação da palestra de Roberto Jerusalem “Por que Lua? (e por que não) ”na conferência Lua em Moscou 2019.

- Para fazer a prĂłxima pergunta, vamos voltar a esta imagem. Se bem entendi, vocĂŞ acha que Lua Ă© uma pequena ferramenta conveniente para resolver tarefas nĂŁo muito grandes.

- Não, acredito que você possa resolver alguns grandes problemas, mas sem envolver análise estática. Eu acredito em testes com todo o meu coração. A propósito, eu não concordo com você em relação à cobertura, que não devemos perseguir a cobertura ... Quero dizer, concordo totalmente com a visão de que a cobertura não fornece testes completos, mas a falta de cobertura não permite testes. Eu falei em Estocolmo sobre a sala de teste, você estava lá. Comecei a testar com [vários] bugs - essa é a coisa mais estranha - um deles era amplamente conhecido e o resto era completamente desconhecido. Algo quebrou completamente no arquivo de cabeçalho Microsoft, C e C ++. Eu procurei na net, mas ninguém estava preocupado com isso ou até percebeu.

Por exemplo, existe uma função matemática modf () , que precisa passar um ponteiro para um valor duplo, porque retorna duas duplas. Convertemos a parte inteira ou fracionária de um número. Esse recurso faz parte da biblioteca padrão há muito tempo. Então veio o C 99, e essa função agora é necessária para números flutuantes. E o arquivo de cabeçalho da Microsoft simplesmente salvou essa função e declarou outra como uma macro. Ou seja, a primeira função passou por conversão implícita de tipo. Double foi convertido em uma bóia e, em seguida, um ponteiro para double foi convertido em um ponteiro em uma bóia!

- Algo está errado com esta imagem.

- Este é o arquivo de cabeçalho do Visual C ++ e Visual C 2007. Se você chamar essa função uma vez, com qualquer parâmetro e depois verificar o resultado, será incorreto, a menos que seja 0. Qualquer outro valor não será verdadeiro. Você nunca pode usar esse recurso. Zero cobertura. E depois houve muita discussão sobre testes ... Basta chamar a função uma vez e verificar o resultado! Esse problema existe há muito tempo, por muitos anos não incomodou ninguém. A Apple tinha um bug muito famoso, algo como " if… what… goto… ok ". Alguém inseriu outra expressão aqui, e tudo se tornou normal. E então eles discutiram muito sobre a necessidade de regras, se chaves devem ser usadas no estilo de código e assim por diante. Ninguém mencionou que existem muitos outros "ses". Ninguém fez isso ...

- Há também um problema de segurança, se bem me lembro.

Isso mesmo. Afinal, eles testam apenas situações confirmadas. Eles não testam tudo em uma linha, porque tudo será confirmado. Isso significa que, no aplicativo que verifica a segurança, não há um único teste que verifique a falha em qualquer conexão ou o que deve ser negado lá. E todo mundo está discutindo se os colchetes são necessários ... Precisamos de testes, pelo menos testes! Afinal, ninguém sequer testou o que quero dizer com "revestimento". Isso é inacreditável, as pessoas nem fazem testes básicos. Obviamente, seria muito difícil fornecer cobertura com testes básicos, executar todas as linhas de código. As pessoas evitam até os testes básicos, portanto a cobertura é mínima. Quero pedir que você preste atenção nas partes do programa que você esqueceu. Algo como uma dica de como melhorar um pouco seus testes.

- VocĂŞ sabe qual cobertura de teste no Tarantool? 83%! Qual Ă© a cobertura em Lua?

- Cerca de 99,6%. Quantas linhas de código você possui? Um milhão, centenas de milhares? Esta é uma quantidade enorme. 1% de cem mil são mil linhas de código que nunca foram testadas. Você não os executou. Seus usuários não estão testando nada.

- Ou seja, cerca de 17% das funções do Tarantool não são usadas agora?

- É improvável que você queira voltar ao que estávamos falando novamente ... Acho que um dos problemas com linguagens dinâmicas (e estáticas também) é que as pessoas não testam seu código. Mesmo usando uma linguagem estática - não como Haskell, mas algo como Coq - até você ter um sistema de verificação, você mudará isso para isso. E nenhuma ferramenta de análise estática pode detectar esses erros, então você precisa de testes. E se você os tiver, poderá identificar problemas globais, erros de digitação em nomes e assim por diante, todos os tipos de erros. Você definitivamente precisa de testes. Às vezes, será difícil depurar, caso contrário, é simples - depende do idioma e do tipo de bug. Mas o ponto principal é que nenhuma ferramenta de análise estática pode substituir os testes. Por outro lado, eles não garantem a ausência de erros, mas com eles me sinto muito mais confiante.

- Temos uma pergunta sobre o teste de módulos Lua. Como desenvolvedor, quero testar algumas funções locais que posso usar mais tarde. Pergunta: você precisa de cobertura no nível de 99%, mas o número de situações funcionais que o módulo para a API deve gerar é muito menor que a quantidade de funcionalidade que ele suporta internamente.

- Com licença, por quê?

- Há funcionalidades que não estão disponíveis para interfaces públicas.

"Ela não deveria estar lá, apenas exclua este código."

- Apenas remova?

- Sim, eu faço isso algumas vezes em Lua. Havia algum tipo de cobertura de código, eu não conseguia chegar aqui, ali ou ali, decidi que era impossível e apenas excluí o código. Raramente, mas acontece. Se algumas situações forem impossíveis, basta escrever nos comentários por que isso não é possível. Se você não pode entrar na função a partir da API pública, não deve ser. É necessário gravar APIs públicas com dados de entrada incorretos, isso é importante para testes.

- A remoção do código é boa, reduz a complexidade. Menos complexidade - maior estabilidade e facilidade de manutenção. Não complique.

- Sim, na programação extrema existe essa regra. Se algo não puder ser testado, ele não existe.

- Em quais idiomas vocĂŞ se inspirou para criar Lua? Quais paradigmas, recursos funcionais ou partes de quais idiomas vocĂŞ gosta?

- Eu projetei Lua para um propósito muito restrito, não era um projeto acadêmico. Então, quando você me perguntou sobre recriar o idioma, respondi que havia uma história inteira por trás dele. Não comecei a desenvolver Lua com "vou criar uma linguagem que gosto, que quero usar ou que todo mundo precisa". Eu tive um problema: aqui eu preciso de uma linguagem de configuração para geólogos e engenheiros, ela deve ser pequena e com uma interface simples para que eles possam usá-la. Portanto, a API sempre foi parte integrante da linguagem. Essa foi a tarefa. Quanto à inspiração, naquela época eu estava familiarizado com cerca de dez idiomas diferentes.

"Gostaria de saber quais idiomas vocĂŞ deseja incluir no Lua."

- Emprestei idéias de várias línguas, tudo o que era adequado para resolver meu problema. A sintaxe da linguagem Modula teve a maior influência, embora seja difícil dizer, porque existem muitas línguas. Algo tirou do AWK. Claro, de Scheme e Lisp ... Eu não sou indiferente ao Lisp desde que comecei a programar.

- E ainda não há macros em Lua!

- Sim, a sintaxe é completamente diferente. Provavelmente a primeira língua era Fortran ... não, minha primeira língua era assembler e depois Fortran. Estudei, mas nunca usei a CLU. Programado muito em Smalltalk e SNOBOL. Também estudou, mas não usou o Icon, também uma linguagem muito interessante. Peguei emprestado muito de Pascal e C. Quando criei Lua, o C ++ já era muito complicado para mim, isso foi antes dos modelos e outras coisas. Comecei a trabalhar em 1991 e lancei Lua em 1993.

- A URSS entrou em colapso e você começou a criar Lua :) Você não gostou do ponto e vírgula e dos objetos quando iniciou o Lua? Pareceu-me que sua sintaxe seria semelhante a C, porque Lua está integrada a ela. No entanto ...

- Eu acredito que a sintaxe deve ser diferente, então você não ficará confuso, porque esses são dois idiomas diferentes.

Isso é realmente engraçado e está relacionado à resposta sobre matrizes que começam com uma que você não me permitiu expressar [na conferência]. Minha resposta foi longa demais.

Quando Lua foi lançada, o mundo estava diferente. Nem todas as linguagens eram semelhantes a C. Ainda não havia Java e JavaScript, o Python era um bebê e não foi além da versão 1.0. Portanto, nem todas as línguas eram semelhantes a C; sua sintaxe era uma de muitas.

A mesma coisa com matrizes. É engraçado que a maior parte disso não esteja ciente. Matrizes começando com 0 e 1 têm seus próprios méritos.

É graças a C que os idiomas mais populares atualmente usam matrizes começando com 0. Seus criadores foram inspirados por C. E é engraçado que não haja indexação em C. , , . , — , (offset). , , , , .

, , . Java, JavaScript — . 0, . , « ».

— , , . -, , , - , , . , Lua ? ?

— ?

— .

— . , , . . ? , , . . .

— Lua C.

— , , . , , … , , - . : , … .

, . , ? , - … ?

— .

— . ? C , , … ?

— 16 ?

— , .

— , , .

— , . , , … , , . — , . , , . , … : ?

— C++ .

— , C++ .

— ? ptrdiff_t ?

— ptrdiff_t — (signed type). , , . ?

, diff , . . , ? De jeito nenhum. , , . 2 , .

, . , . diff , .

, ++.

— Lua ?

— , C++, - , . , - ++, … .

— , ?

— . , . , , . , .

— JVM?

— , JVM. , … — , . JVM , .NET, . JVM , Lua. , . JVM, . JVM . Java-, 10 . , JVM , .

— JVM, , Mobile JVM?

— , JVM. - Java, Java.

— , Go Oberon? Lua, ?

— Oberon… … Go , runtime- Lua. Oberon , . , , . , , const Pascal Oberon. , . .
, 1994- Oberon Self. Self? JIT- . Self , , . - , — ! — , - . , …

Oberon, , 10 Self, . Oberon , , .

, .

— Haskell?

— Haskell, , Lua.

— Python, R Julia Lua?

— , .

R . , .

Python , . , . , .

Python , , . , , - . API… , Python, . , , « ».

, -: , , , -. . , API , - . , . , , …

- , (pattern matching). , , , . , , .

: Perl. Lua, . , Python . , , . - .

— ?

— Python. Perl : $1, $2, $3. Perl, …

— Python, , ( Tarantool).

— , , , API, . Python , .

Julia, LuaJIT, , . , , . , . , , , . , , . : , - . , , - , .

Julia, : , , . , - . , double, []… . .

() «, , , , , . , ». , , .

. R, Python.

— Erlang?

— . , . , , , - . Erlang , , . , .

, . , . ? , . .

— , Erlang , Python . Lua?

— , . Lua , , Lua , .

— ?

— Forth, .

— Lua?

— , . , . - , . Lua, Lua, .

Java. Java, ? NĂŁo. (reflection)? NĂŁo. ? Java, , Java. , , Java, .

, Lua, … , , FFI.

— Lua?

— , .

— Lua ? ?

— , . , Haskell. , , … Lua, , , , , .

— , Lua.

— , , . . , .

— , . Lua ?

— , , …

— « »? , ?

— , . , , , . , .

— Lua?

— . , , LaTex DocBook. , … LaTex, . @, . Gsub , , - - . , , , .

— LaTeX?

— LaTeX? -, , . , , LaTex. , inline-. /, . — . , , , . , . , .

— LaTeX?

— , . , , . , 3+1, . , , . , . , , . , 1 «and», . . , .

— ?

— , git . 2html . HTML… , . , , . , , . , TeX. TeX- TeX.

— ?

— , . , TeX. , . DocBook, . , .

— 2html DocBook?

— , DocBook.

— , , !

— .



- , Lua Mailing List .

Source: https://habr.com/ru/post/pt459464/


All Articles