Janet para Mortais (2023)
(ianthehenry.com)- Janet for Mortals é um livro online gratuito sobre a linguagem de programação Janet, mas o foco da retrospectiva está menos no livro em si e mais no processo de produção de uma obra técnica que também incluiu um REPL web e projetos de exemplo
- O trabalho completo levou 20 semanas, passando da estimativa inicial de 12 semanas só de escrita, porque vieram junto tarefas extras como o site, bindings em C++, demos no navegador, um parser de CLI e ferramentas de teste
- O site do livro oferece um REPL embutido com CodeMirror e gramática Lezer; o autocompletar consulta o ambiente Janet via WebAssembly e
(report)salva feedback em SQLite cmd,judge,to doe Toodle.Studio servem como exemplos-base para mostrar que Janet pode ser usada para scripting, ferramentas de CLI, testes, execução no navegador e interoperabilidade com JavaScript- Logo após o lançamento, só com envios ao Hacker News e Lobsters, houve 30.025 visitantes únicos na sexta, 9.568 no sábado e 3.777 no domingo, mas estima-se que apenas 387 IPs únicos leram 5 capítulos ou mais
Escopo do livro e volume real de trabalho
- Janet for Mortals é um livro online gratuito sobre a linguagem de programação Janet
- O período total de produção foi de 20 semanas em tempo livre
- A estimativa inicial era de 12 semanas e, considerando apenas o tempo de escrita do texto em inglês, não ficou tão longe disso
- Na prática, o cronograma acabou incluindo bastante trabalho de programação em torno do livro
- O tamanho final, excluindo trechos de código, foi de 44.000 palavras de prosa em inglês
- Como comparação, The Great Gatsby tem 47.000 palavras
- É menos da metade do tamanho da série anterior de textos sobre Nix
- Ao longo de 5 meses, além do livro, também foram feitos os seguintes trabalhos
- site do livro
jimmy: binding para uma biblioteca C++ de estruturas de dados persistentes- Toodle.Studio: playground interativo de turtle graphics
cmd: biblioteca de parsing de argumentos de linha de comandojudge: framework de testes com snapshots inlineto do: gerenciador de lista de tarefas em linha de comando
O site e o REPL embutido
- O principal recurso do site de Janet for Mortals é o REPL embutido
- O usuário pode abrir o REPL a qualquer momento com a tecla Escape
- O REPL fica fixo na parte inferior da página, sem cobrir muito o texto principal
- O editor usa CodeMirror
- O CodeMirror não oferece suporte a Janet por padrão
- A base veio do suporte à linguagem Janet criado anteriormente para o projeto Bauble
- Sintaxes de Janet que não eram importantes no DSL do Bauble, como strings
multi`backtick`quoted, passaram a ser necessárias no livro
- Ao reforçar a gramática Lezer usada pelo CodeMirror, a mesma gramática também foi reutilizada para o realce de sintaxe dos trechos de código do livro
- Não foi encontrado nenhum gerador de site estático conhecido com suporte a highlighting de código Janet
- No começo o livro era em preto e branco, mas depois foram adicionadas cores para tornar a sintaxe pouco familiar de Janet mais amigável
- O gerador de site estático foi escrito manualmente usando
redo- O núcleo do gerador foi escrito em JavaScript, o que permitiu acoplar a gramática Lezer
- A estrutura geral inteira era frágil e conectada com shell
- Remark foi usado tanto para fazer parsing do texto-fonte do livro quanto no REPL do cliente
- Foi adicionada uma extensão simples para rotular blocos de código
- As docstrings da biblioteca padrão de Janet são escritas em Markdown, então são renderizadas em HTML na hora dentro do autocompletar do REPL
Autocompletar e feedback unidirecional
- O autocompletar do REPL foi tratado como algo importante para leitores vendo Janet pela primeira vez
- Na inicialização do REPL, o ambiente Janet é consultado dinamicamente via WebAssembly
- Mesmo que o usuário defina um novo símbolo com docstring, ele não aparece nos resultados do autocompletar
- Seria possível recriar o autocompletar após cada execução de comando, mas isso foi considerado pouco valioso
- A função
(report)recebe uma string, faz POST para um servidor web simples, e o servidor salva isso em um banco SQLite- É parecido com uma caixa de comentários, mas com o diferencial de poder enviar direto do REPL
- Esse recurso permitiu ler feedback e corrigir vários erros
- Não foi implementada nenhuma forma de responder
- O backend de report não é em Janet, mas sim uma pequena aplicação em Haskell
- Ela apenas recebe requisições POST e as grava em um banco SQLite
- O servidor web não foi feito em Janet
- Segurança foi considerada o fator mais importante num servidor web
- Janet e as bibliotecas HTTP de Janet não foram vistas como suficientemente validadas para ficarem expostas diretamente à internet
jimmy: experimento de interoperabilidade com C++
jimmyé um binding de Janet para immer- immer é uma biblioteca de estruturas de dados persistentes
- O binding não foi concluído e provavelmente não será finalizado até surgir uma necessidade real de uso
- Ainda assim, foi considerado um exemplo bem-sucedido de como fazer interoperabilidade com código C++ a partir de Janet
Toodle.Studio e Janet no navegador
- Bauble era um pequeno playground artístico criado anteriormente e foi a primeira experiência de embutir Janet no navegador
- Na época havia pouco material sobre embedding de Janet
- Como era preciso usar WebAssembly, Emscripten e TypeScript no navegador, o nível de dificuldade era alto
- O resultado final de Bauble foi um site cuja lógica da aplicação era escrita em Janet
- A UI usava bastante JavaScript, mas a lógica central ficava com Janet
- Uma das principais motivações para escrever o livro foi tornar mais acessíveis as técnicas de usar Janet no navegador
- No livro, em vez de Bauble, foi criado Toodle.Studio como exemplo
- Bauble não tinha estado e se parecia mais com uma função pura que transforma string em string, então era simples do ponto de vista de interoperabilidade
- Toodle.Studio é claramente um fork de Bauble, mas a interoperabilidade entre JavaScript e Janet nele é mais complexa
- Toodle.Studio tinha elementos técnicos mais adequados para servir de exemplo no livro
- Programas Janet de longa duração precisam ser executados de forma assíncrona ao longo do tempo
- Como o código JavaScript mantém várias referências para o mesmo valor Janet, é preciso considerar gerenciamento de memória
- Estruturas de dados aninhadas complexas precisam ir e voltar entre Janet e JavaScript passando por C++
- O logo do Toodle.Studio é uma tartaruga animada feita com Bauble
- Ela foi adicionada depois de um feedback dizendo que um demo de turtle graphics sem tartaruga não fazia sentido
- Os olhos foram feitos para seguir o mouse
cmd: parser de argumentos de CLI para Janet
cmdé uma biblioteca de parsing de argumentos de linha de comando- No livro ela aparece por apenas uns três parágrafos, mas era necessária para mostrar com clareza que Janet é uma boa linguagem de scripting
cmdfoi fortemente influenciado porCore.Commanddo OCamlCore.Commandfoi considerado o melhor parser de argumentos de linha de comando já usado- A ideia era recriar essa experiência em Janet
cmdnão é tão bom quantoCore.Command- Com tipos, tudo fica muito mais fácil
- Ainda assim, ele tem 95% dos recursos considerados importantes e, por causa da sintaxe concisa, foi visto como até mais confortável para scripts ad hoc
- Ainda falta a geração de funções de autocompletar para Bash
Core.Commandgera isso automaticamente- A API de
cmdfoi desenhada para permitir adicionar esse recurso depois
judge: framework de testes com snapshots inline
judgefoi uma das primeiras coisas feitas em Janet, em 2021- Depois de conhecer melhor Janet, ele foi reescrito do zero
- A API ficou mais agradável de usar
- A implementação também ficou muito mais simples e fácil de modificar
- A principal diferença entre Judge v1 e v2 está na localização dos testes e nos helpers
- Os testes podem ficar não só no diretório
test/, mas também dentro de arquivos normais de código-fonte - Foram adicionados os helpers
test-macroetest-stdout
- Os testes podem ficar não só no diretório
- Foi dito que o equivalente em OCaml de
test-stdouté praticamente a única forma usada profissionalmente para escrever testes- Em OCaml não há uma boa maneira de embutir dados arbitrários no código-fonte, então a abordagem acaba sendo transformar tudo em string
- Depois do lançamento do livro, foi adicionado ao Judge um modo
--interactive- O livro tem um capítulo sobre testes e debugging com Judge
to do: ferramenta de tarefas feita em Janet no lugar de Bash
to dofoi escolhida como exemplo no capítulo de scripting- Era uma ferramenta não trivial feita anteriormente em Bash, e a implementação em Bash foi dolorosa
- As partes mais difíceis em Bash eram especialmente parsing de texto e tratamento de datas
- Fazer parsing de texto multilinha com Sed não era nada agradável
- Manipular
datede forma que funcionasse igual no macOS e no Linux foi visto como praticamente impossível
- Em Janet, usando PEG,
sh,cmde mais algumas coisas, foi possível criar mais recursos mais rápido do que na lista de tarefas original em Bash- Por exemplo, foi adicionada seleção múltipla com
fzf - Em Bash, montar strings terminadas em null foi considerado difícil
- Por exemplo, foi adicionada seleção múltipla com
- O livro cobre apenas uma versão simplificada
- Sem recurso de agendar tarefas futuras
- Sem o conceito de “pular” tarefas
- Os recursos centrais são adicionar itens à lista e marcá-los como concluídos
- Em conjunto com
zsh-autoquoter, ela foi considerada um app surpreendentemente útil
Trabalho de código durante a escrita e manutenção
- Das 20 semanas de trabalho no livro, a programação ocupou quase metade
- 8 semanas foram de trabalho de código, e em alguns períodos houve escrita e programação ao mesmo tempo
- No início, só eram esperadas melhorias no Judge e a criação do parser de argumentos
- Implementar o parser de argumentos foi muito mais difícil do que o previsto
- Como Bauble era simples demais, não se imaginava que seria preciso criar outro playground artístico novo
- A escrita em si foi feita em Markdown no Sublime Text
- O Sublime Text é o editor preferido para escrever prosa longa
- Durante a escrita saíram 2 novas versões de Janet
- Foi preciso atualizar os capítulos sobre debugging e módulos nativos para acompanhar as mudanças da linguagem
- A intenção é manter o livro atualizado com as releases mais recentes de Janet
Reação ao lançamento e quanto de fato foi lido
- A divulgação do livro foi basicamente envio ao Hacker News, envio ao Lobsters e alguns tweets
- No Hacker News ele ficou na front page o dia inteiro e por um tempo ocupou o primeiro lugar
- Segundo os logs de acesso do Nginx, os visitantes únicos foram os seguintes
- Sexta-feira: 30.025
- Sábado: 9.568
- Domingo: 3.777
- Esses números parecem mais próximos da quantidade de pessoas que clicaram no link do que da quantidade de pessoas que realmente leram o livro
- O site não tem analytics com rastreamento de comportamento no cliente
- Só foi possível fazer uma estimativa aproximada com base nos logs de acesso
- O fluxo de visita entre capítulos indicou retenção ruim
- O capítulo 1 teve 22% das visitas da home page
- O capítulo 2 teve 20% das visitas do capítulo 1
- O capítulo 3 teve 69% das visitas do capítulo 2
- O capítulo 4, “Pegular Expressions”, e o capítulo 9, “Xenofunctions”, tiveram mais visitas do que o capítulo 3
- Ao fim do fim de semana de lançamento, a melhor estimativa do número de leitores reais era de 387
- O critério usado foi a quantidade de IPs únicos que carregaram 5 ou mais capítulos diferentes
Origem do nome e limites revelados pelo feedback
- O nome da linguagem Janet vem de Janet, o ser imortal de The Good Place
- Como essa personagem ajuda mortais a se moverem pela vida após a morte, isso também se conecta ao título do livro
- O capítulo com menos visitas foi “Testing and Debugging”
- É o terceiro a partir do fim do livro
- Os três capítulos finais foram considerados os mais interessantes do livro
- O estilo de teste desse capítulo foi visto como um dos maiores ganhos de produtividade em toda a carreira de engenharia da pessoa autora
- Foram recebidos 494 feedbacks pela função report do REPL embutido
- Muitos eram só mensagens do tipo “bom livro” ou testes
- Dezenas eram avisos de typo, pedidos de explicação e comentários úteis
- Alguns usuários enviaram perguntas sem deixar contato, e como não existe recurso de resposta, não foi possível responder
- A função report foi implementada como um recurso muito primitivo de feedback unidirecional
1 comentários
Comentários do Hacker News
Também não dá para deixar de mencionar https://bauble.studio/ do mesmo autor
No navegador do meu computador velho não roda, mas quando estou estudando na biblioteca e quero dar uma pausa, às vezes fico uns 30 minutos brincando com o bauble no computador de lá
A quantidade de gráficos que dá para criar só mexendo nos números é enorme, e espero que Janet dure por muito tempo
unknown symbol twisterror: script:16:1: compile error: unknown symbol twistin evaluate [lib/evaluator.janet] on line 81, column 7in bauble-evaluator/evaluate [lib/init.janet] on line 8, column 12É interessante comparar Janet com GNU Guile
A vantagem original do Guile era ser uma linguagem feita para funcionar facilmente lado a lado com C, mas por ser antiga parece que ainda não assimilou sensibilidades mais modernas, como incluir um gerenciador de pacotes por padrão no toolchain da linguagem
Uma coisa de que gosto no Guile é o grande esforço feito para explicar sua compatibilidade com o padrão RNRS
Não sei o quanto Janet realmente se parece com Scheme, mas fico curioso
Está mais para alguém ter feito Clojure em cima de Lua
O livro é https://janet.guide/ e a linguagem está em https://janet-lang.org/
Gostei da abordagem prática do livro, e isso é um dos principais motivos de eu estar aprendendo ao resolver o Everybody Codes em Janet
https://everybody.codes
A frase “a tartaruga é uma metáfora” é meio decepcionante
A tartaruga não era uma metáfora, era real: http://classicacorn.computinghistory.org.uk/8bit_focus/logo/...
Claro, encaixa na definição de metáfora como “algo que representa outra coisa, um símbolo”, mas soa como aquela piada de confundir o ícone de salvar em disquete com uma geladeira
Parece que faltou o contexto de que antigamente existiam tartarugas de hardware reais, divertidas e fofas
Só pelo título, achei que fosse outro assistente de IA inspirado na Janet de The Good Place, mas fiquei agradavelmente surpreso ao ver que era uma linguagem de programação
A linguagem Janet recebeu o nome da entidade imortal Janet, de The Good Place, que ajuda humanos a navegar pela vida após a morte, então o título também é uma piada inteligente nesse sentido
Também me surpreendeu que ela ofereça PEG (gramática de expressão de parsing) em vez de um mecanismo de regex padrão
Sempre quis que linguagens com biblioteca padrão de regex também viessem com um PEG decente
Veja <https://www.gnu.org/software/guile/manual/html_node/PEG-Pars...>
sporkde Janet ocupa meio que o papel de uma libc, e também tem um submódulo de regex, então é bem provável que esteja instaladoConheci PEG pela primeira vez em Janet, e gostei de como ele é poderoso e fácil de usar
Mexo com regex há mais de 20 anos aos poucos, mas em poucos meses passei a entender PEG melhor
A comunidade Janet também está cheia de referências a The Good Place, e vários módulos de terceiros receberam nomes dos personagens
elm/regexeelm/parsernão são embutidos, maselm/regexrecomenda usar elm/parser no lugarGosto da origem do nome, mas uma linguagem chamada Janet também parece ter a obrigação de priorizar controle
Li o livro, e ele é bem interessante e brincalhão, então tornou o aprendizado de Janet muito mais divertido
Só que a documentação da linguagem deixava a desejar em vários aspectos
Muitas vezes as funções ou comandos eram apenas listados, sem exemplos ou explicações, ou sem dizer o que faziam
Houve muitos casos em que vi algo no livro e não consegui encontrar na documentação, e isso foi um dos motivos de eu gostar de Janet mas ainda assim parar de aprender
Gosto de ela ter muitos padrões sensatos e de se parecer com linguagens mainstream em vez de insistir em convenções velhas de Lisp
No fim das contas, como não é uma lista cons, não é realmente Lisp, mas tudo bem
O problema é que a linguagem não está bem documentada o suficiente
Participo razoavelmente da comunidade Janet, então, se eu souber onde faltam coisas, posso contribuir para melhorar a documentação
Às vezes só havia a assinatura da função, sem nenhuma explicação adicional
Entendo que criar documentação ampla exige muito tempo e esforço, mas isso acontecia com tanta frequência que acabei desistindo e comecei a procurar outro Lisp que compilasse para binário
Não consegui me adaptar muito bem ao Janet, mas não sei se o problema sou eu
O único outro Lisp que usei por bastante tempo foi Emacs Lisp, e Janet é parecido o suficiente, mas sutilmente diferente, a ponto de eu continuar cometendo errinhos bobos
O recurso de PEG parecia atraente na documentação, mas a sintaxe era desconfortável e confusa de usar
A documentação era completa no sentido de ter descrição de todas as funções, mas muito sucinta por faltar exemplos e informações úteis de uso
Nem parecia incluir funções básicas como parsing de JSON
Se numa linguagem para escrever scripts rápidos eu já preciso começar implementando um parser de JSON ou XML, então a tarefa já falhou
Isso foi há uns 4 anos, então talvez o ecossistema tenha melhorado, ou talvez meu critério para avaliar Janet como linguagem de script estivesse errado
Ainda assim, este texto me deu vontade de instalar de novo
spork, que ocupa algo como o papel de uma libcHá uma orientação interna forte de manter o núcleo leve
Muitos projetos dependem de
spork, então é provável que ele venha instalado logo de inícioConcordo que a documentação é razoável, mas ainda há lacunas em exemplos práticos
O https://janetdocs.com ajuda a cobrir isso, com links para “exemplos da comunidade” por função
Fugindo um pouco do assunto, foi graças a outro post do blog original que comecei a usar um teclado mecânico dividido
Eu tinha dores no ombro e no punho havia anos, e isso ajudou; recomendo fortemente dar uma olhada também nos outros textos do Ian
Ter a qualquer momento a possibilidade de apertar
Escpara abrir um REPL embutido preso na parte de baixo talvez não seja uma boa decisãoO navegador já tem um atalho padrão em
Esc, e no Firefox apertarEscsai do modo de tela cheia