
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 .