2 pontos por GN⁺ 2024-11-29 | 1 comentários | Compartilhar no WhatsApp
  • 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 do e 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 comando
    • judge: framework de testes com snapshots inline
    • to 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
  • cmd foi fortemente influenciado por Core.Command do OCaml
    • Core.Command foi considerado o melhor parser de argumentos de linha de comando já usado
    • A ideia era recriar essa experiência em Janet
  • cmd não é tão bom quanto Core.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.Command gera isso automaticamente
    • A API de cmd foi desenhada para permitir adicionar esse recurso depois

judge: framework de testes com snapshots inline

  • judge foi 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-macro e test-stdout
  • 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

to do: ferramenta de tarefas feita em Janet no lugar de Bash

  • to do foi 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 date de forma que funcionasse igual no macOS e no Linux foi visto como praticamente impossível
  • Em Janet, usando PEG, sh, cmd e 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
  • 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

 
GN⁺ 2024-11-29
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

    • Num MacBook Pro M1 Max modelo 2021, com MacOs 15.1.1, funciona no Chrome, mas no Firefox dá erro de compilação unknown symbol twist
      error: script:16:1: compile error: unknown symbol twist
      in evaluate [lib/evaluator.janet] on line 81, column 7
      in 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

    • Janet não tem nada de Scheme
      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

    • Não sei se o que aparece naquela página dá para chamar de tartaruga “de verdade”
  • 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

    • O GNU Guile também tem uma biblioteca de PEG na biblioteca padrão
      Veja <https://www.gnu.org/software/guile/manual/html_node/PEG-Pars...>
    • O módulo spork de 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 instalado
      Conheci 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
    • O Elm adota uma abordagem parecida
      elm/regex e elm/parser não são embutidos, mas elm/regex recomenda usar elm/parser no lugar
      Gosto 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

    • Você lembra de alguma função ou comando que não estivesse documentado?
      Participo razoavelmente da comunidade Janet, então, se eu souber onde faltam coisas, posso contribuir para melhorar a documentação
    • Tive exatamente a mesma experiência, tirando a parte de não ter lido o livro
      À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

    • Coisas como JSON e regex estão no módulo spork, que ocupa algo como o papel de uma libc
      Há 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ício
      Concordo 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 Esc para abrir um REPL embutido preso na parte de baixo talvez não seja uma boa decisão
    O navegador já tem um atalho padrão em Esc, e no Firefox apertar Esc sai do modo de tela cheia