Λ-2D: explorando o desenho como linguagem de programação
(media.mit.edu)- λ-2D é um experimento de linguagem em que o próprio desenho funciona como código, buscando ao mesmo tempo expressões visuais difíceis de tratar em linguagens textuais e a forma estética do programa
- A espinha dorsal da linguagem é o cálculo lambda, partindo da ideia de que uma estrutura mais próxima de avaliação do que de uma ordem fixa de execução se parece com a forma como observamos um desenho
- Para ser fácil de desenhar à mão e ainda interpretável por máquinas, ela usa símbolos baseados em grade e fios para representar o fluxo de dados
- Como o uso apenas de cálculo lambda puro tem baixa usabilidade, foram adicionados açúcares sintáticos e elementos de interação como números, operadores matemáticos, quadros e sliders
- A implementação atual converte programas λ-2D em uma única expressão JavaScript para execução, mas ainda restam limitações como a aparência de diagrama de circuito e desafios de aprendizado e escaneamento
Experimento de linguagem para programar com desenhos
- λ-2D é um experimento de linguagem de programação não verbal que parte da pergunta: “é possível programar por meio de desenhos?”
- Já existem vários ramos de linguagens não textuais
- O objetivo do design se resume em três pontos
- Aproveitar o fato de que o programa é desenhado para incluir recursos difíceis de realizar em linguagens baseadas em texto
- Evitar situações em que haja comandos tão poucos que até programas simples fiquem difíceis, ou tantos que a linguagem deixe de ser minimalista e o processamento por visão computacional se torne difícil
- Fazer com que o próprio programa seja visualmente atraente, a ponto de virar um desenho que daria vontade de colocar numa moldura
Cálculo lambda e representação baseada em grade
- λ-2D usa o cálculo lambda como base da linguagem, em vez de uma abordagem imperativa ou de baixo nível
- O cálculo lambda é mais próximo de “avaliação” do que de “execução”, e isso se conecta à forma como o olhar percorre pontos, linhas, formas e composição em um desenho, sem uma ordem específica
- A estrutura inicial é um sistema baseado em grade
- O usuário pode desenhar uma linha contínua atravessando várias células da grade
- Cada célula é, no fim, interpretada como um entre um conjunto finito de símbolos
- É um meio-termo entre algo fácil de desenhar para humanos e fácil de analisar para computadores
Símbolos de função e fluxo de dados por fios
- O cálculo lambda tem apenas dois comandos básicos
- aplicação de função
- definição de função
- λ-2D representa a aplicação de função com um símbolo em forma de xícara e a definição de função com a letra grega λ
- Como no cálculo lambda básico, uma função sempre recebe um único argumento e produz uma única saída
- Para lidar com vários argumentos, usa-se currying, conectando várias funções
- Os fios entre os símbolos funcionam como canais por onde os dados fluem
- Nessa etapa a linguagem é tecnicamente Turing completa, mas o uso prático é muito incômodo, então foram adicionados símbolos extras, como números e operadores matemáticos
- Esses símbolos extras são açúcar sintático
- Se quiser, ainda é possível usar apenas estruturas de cálculo lambda puro, como numerais de Church
Quadros, dados de desenho e sliders
- λ-2D tenta estender de forma mais natural a experiência do Scratch, em que se desenha um sprite no mesmo editor e o usa imediatamente
- Os quadros funcionam cercando uma área específica da tela com fios e colocando um símbolo de exibição no canto superior esquerdo
- Os rabiscos dentro da área podem ser usados como dados
- Dá para esboçar diretamente a forma de uma função matemática e usá-la em animações, por exemplo
- A forma é tratada como dado sem precisar de uma etapa separada para encontrar a equação correspondente
- Também foram introduzidos sliders que podem ser arrastados em tempo de execução
- Eles servem para controlar o programa de forma parametrizada
- Outros elementos de GUI podem ser considerados no futuro
Editor e símbolos 5×5
- A ideia inicial veio de programas de exemplo desenhados à mão em um caderno pontilhado
- Como a parte de visão computacional para escanear programas no papel ainda não estava pronta, primeiro foi criado um editor simples para desenhar programas digitalmente
- Cada símbolo é feito com 5×5 pixels, para ser fácil de marcar em uma tela em grade
- O usuário também pode fazer desenho à mão livre, como com uma ferramenta de lápis
- O editor, que começou como uma solução temporária, foi aos poucos se aproximando de um editor com vários recursos
O problema da saída em uma linguagem puramente funcional
- λ-2D é puramente funcional e não tem estado, então é difícil implementar um comando
printconvencional - Saída envolve mudança de estado e, para esperar que algo seja exibido em uma ordem específica, seria preciso também assumir uma ordem de avaliação da expressão
- A solução é redefinir “saída” de forma funcional
- Passa-se uma tela vazia para uma função
- Recebe-se de volta uma nova tela com pixels alterados para parecer texto ou qualquer rabisco desejado
- A linguagem foi projetada com foco em telas e pixels, e não em strings e caracteres
Conversão para JavaScript e visualização da execução
- O parser básico converte o programa λ-2D inteiro em uma expressão JavaScript equivalente
- O JavaScript resultante é uma única expressão gigantesca cheia de parênteses, ineficiente, mas funcional
- Como o parser atual gera JavaScript e delega a execução ao motor JavaScript do navegador, é difícil visualizar o processo real de execução
- Em compensação, o processo de parsing pode ser visualizado com facilidade, e pode se parecer com o caminho percorrido quando um interpretador que caminha pela árvore executa o programa
- Ao adicionar sons por símbolo à animação do parsing, é possível até “ouvir” a execução do programa como se fosse uma música
- O resultado fica mais próximo do som de um jogo de computador estranho da era 8-bit
- Isso pode ser visto na demo online em
Menu > Program > Animated Run
Limitações restantes e próximos passos
- λ-2D começou como parte de uma pesquisa maior sobre desenhar programas com caneta e papel e receber feedback interativo por realidade aumentada
- À medida que o projeto foi ficando mais interessante, ele se tornou um projeto independente
- Os objetivos iniciais ainda não foram totalmente alcançados
- Os programas tendem a parecer mais diagramas de circuito do que desenhos
- É difícil ter certeza de que será fácil para pessoas comuns aprenderem
- Também pode não ser simples fazer um sistema de visão computacional escanear tudo sem erros
- Depois de refinar mais o λ-2D, há planos de projetar outras linguagens de programação que possam ser integradas a sistemas que tratam desenhos como computação
- A versão beta do λ-2D pode ser testada online, e o código-fonte do parser e do editor deve ser publicado em breve no GitHub
1 comentários
Opiniões no Hacker News
Se você gosta desse tipo de coisa, trabalhar como engenheiro de projetos de automação pode ser divertido, ou no mínimo parecer familiar.
Diagramas de blocos funcionais (FBD) são bem parecidos: blocos funcionais são conectados por linhas, e a ordem das operações é definida pela ordem dos blocos. Os próprios blocos podem ser como funções integradas do motor ou blocos compostos. O diagrama é executado uma vez por ciclo de controle e, normalmente, se não houver blocos de salto, cada bloco é executado exatamente uma vez por ciclo de controle, independentemente de as entradas terem mudado ou não.
A lógica de controle de tudo, de cervejarias a plantas petroquímicas, é implementada dessa forma. Trabalho na parte de UI de sistemas de controle baseados em FBD, então vejo essas coisas todos os dias.
É parecido com o BitGrid[1], mas não é a mesma coisa. Imagine uma forma extremamente simplificada de FPGA, em que bits marcham em paralelo por uma grade.
Essa ideia pode ou não ter uma utilidade enorme — petaflops para as massas —, e no fim tudo depende de quanta energia um único DFF consome em um ASIC. O número que venho procurando há tempos é a potência estática e a energia para carregar um bit.
O modelo de programação também é um problema. Ninguém quer posicionar lógica diretamente em uma grade; todo mundo tenta abstrair isso o mais rápido possível. Não tenho foco suficiente para resolver essa parte.
Ao explorar isso, descobri o autômato celular de Von Neumann[2] e os autômatos celulares de Nobili[3], que eu nunca tinha visto, apesar de ter me interessado por ideias parecidas por décadas. Essa área da ciência da computação tem uma descobribilidade tão baixa que chega a ser frustrante.
Ambos compartilham a mesma base absurda. Um conjunto de FSAs define um espaço de células de tamanho infinito, e todos os FSAs têm a mesma função de transição de estados ou conjunto de regras. Sinto que é justamente essa única “simplificação” que empurra tudo para o território de code golf.
[1] https://github.com/mikewarot/Bitgrid
[2] https://en.wikipedia.org/wiki/Von_Neumann_cellular_automaton
[3] https://en.wikipedia.org/wiki/Nobili_cellular_automata
Se alguém quiser tocar adiante a ideia do BitGrid, eu agradeceria.
Na parte “tecnicamente, neste ponto a linguagem é Turing-completa, mas é extremamente dolorosa de usar, violando minha regra de design nº 2”, meus Lambda Diagrams[1] pararam no estágio 1.
No fim daquela página estão links para todas as outras notações gráficas de cálculo lambda que conheço, e acabei de adicionar esta também.
[1] https://tromp.github.io/cl/diagrams.html
Acho uma conquista bem legal, já que agora dá para afirmar que é uma linguagem que faz o navegador dizer “para mim isso é tudo grego!”.
Deixamos essas coisas para trás nos anos 90, quando telas de alta resolução apareceram.
https://worrydream.com/AlligatorEggs/
Já tentamos coisas assim também no LabVIEW, e dá para ver que é difícil ir muito longe. Isso também foi feito em programas de geração de som/música, e o Max [max] é meio que o precursor.
Dá para construir algo, mas logo vira bagunça. Se fica bonito? Eu diria que não.
[max] https://en.wikipedia.org/wiki/Max_(software)
Fluxos de sinal complexos são muito mais fáceis de acompanhar em uma disposição visual, especialmente em diagramas com valores numéricos em tempo real animados, do que em blocos estáticos de texto.
O Max/MSP recente também tem
mc, que oferece conexões multicanal para múltiplos sinais idênticos sem precisar criar linhas/nós separados, e~gene JavaScript permitem nós de programação baseados em texto.Essas “linguagens de programação em blocos” parecem promissoras porque abstraem por meio de caixas-pretas e criando caixas dentro de caixas. Fico me perguntando se o problema é implementação ruim, uso ruim ou se o paradigma em si não funciona.
Um ponto a considerar é que essas ferramentas geralmente são usadas por pessoas que não conhecem programação nem abstração. Alguém bom em programação talvez não fizesse bagunça, mas aí fica meio ambíguo, porque essa pessoa poderia simplesmente escrever código.
Concordo que LabVIEW é horrível. Não só por esse problema: atualizações quebram tudo, há a questão das licenças, enfim, é só dor de cabeça.
Havia uma pequena comunidade de desenvolvedores profissionais de LabVIEW, e no geral eles escreviam código muito bom e bastante legível. Era diferente do jeito com que a maioria está acostumada, mas era bom.
Dito isso, deixei esse mundo alguns anos atrás, porque os sinais eram claros de que, independentemente do que fosse possível fazer, o LabVIEW acabaria morrendo.
Desde que ouvi falar de redes de Petri pela primeira vez, há cerca de 10 anos, tenho interesse em especificações formais gráficas
Sempre achei que, se houvesse representações gráficas em vez de notações matemáticas e linguagens assustadoras, os engenheiros aproveitariam melhor os métodos formais. Infelizmente, sempre que eu mostrava redes de Petri a outros engenheiros, eles perdiam o interesse quase imediatamente
Antes de abandonar meu doutorado na University of York, trabalhei com algo chamado RoboChart e RoboSim[1], que talvez seja mais acessível na prática. Mas é bastante preso à semântica de robótica. Como projeto pessoal, tenho tentado adaptar e expandir o RoboSim para ser mais útil no mundo de redes e servidores
[1] https://robostar.cs.york.ac.uk/robotool/
Gostei muito disso. Especialmente por ter sido implementado em JavaScript
Os puristas vão se revirar na cama ou no túmulo, mas pelo menos as etapas seguintes de visualização e áudio certamente ficaram mais fáceis. O visual é incrível, e o próximo passo parece ser traduzir de alguma forma a estrutura de alto nível de programas existentes para esse formato. Imagino que haja bastante nerd disposto a pagar para pendurar na parede o algoritmo de Dijkstra ou o algoritmo de retropropagação de uma rede neural artificial
A parte que achei interessante foi a de que a linguagem é tão puramente funcional e totalmente sem estado que não dá para implementar uma instrução
print. Produzir saída é alterar estado, e esperar que a saída apareça em uma ordem específica é assumir que as expressões são avaliadas em alguma ordemIsso não é simplesmente dizer que “não é imperativa”? Ainda assim, fico curioso para saber como o estado poderia ser codificado. Talvez introduzindo variáveis, por exemplo ícone+cor, e permitindo alinhar instruções individuais ao longo de um eixo ou de ambos
“A área de linguagens de programação não verbais não é inexplorada”
Já começa na segunda frase com uma agressiva tripla negação
Isso me lembrou Wireworld, de 1987. Claro que também há um artigo na Wikipedia [1]
Já vi um contador de 8 bits implementado em Wireworld e era bem impressionante. Mas isto parece um pouco mais conciso
[1]: https://en.wikipedia.org/wiki/Wireworld
Só que hoje é difícil jogar. A página web[1] e a versão da Steam dependiam de Flash, então é preciso mexer com reimplementações de Flash de terceiros
Ainda assim, acho que a implementação do funcionamento de semicondutores é muito melhor que em Wireworld
[1] https://www.zachtronics.com/kohctpyktop-engineer-of-the-peop...
Link direto para a demo online: https://l-2d.glitch.me/
Outros ambientes/linguagens de programação bem visuais que encontrei. São diferentes de outras formas de programação visual que conectam nós com linhas
Dá para classificar de outra forma, mas não sei como chamaria
Piet https://www.dangermouse.net/esoteric/piet.html
Turnstyle https://jaspervdj.be/turnstyle/ https://github.com/jaspervdj/turnstyle
Markovjunior https://github.com/mxgmn/MarkovJunior
Cellpond https://cellpond.cool/ https://github.com/TodePond/CellPond https://www.youtube.com/watch?v=xvlsJ3FqNYU
Imagegram https://zaratustra.itch.io/imagegram
Color Code http://colorcode.bananabanana.me/ https://www.youtube.com/watch?v=5M5hy9xsqKc Color Code 2 http://colorcode2.bananabanana.me/ https://www.youtube.com/watch?v=tTvvX4sjZWw Splaty Code http://splatycode.bananabanana.me/ https://www.youtube.com/watch?v=gd_e85lAKOs (feito por Muril Polese https://github.com/murilopolese/ http://gallery.bananabanana.me/)
Alchemy Online https://maxbittker.github.io/alchemy-online/ https://github.com/MaxBittker/alchemy-online