- Hurl é uma linguagem de programação experimental que constrói o fluxo de controle usando apenas tratamento de exceções, em vez de desvios ou laços comuns
- Surgiu de uma conversa entre Nicole Tietz-Sokolskaya e amigos do Recurse Center, e o site oferece documentação de uso, exemplos, orientações de depuração e perguntas e respostas
- Os depoimentos na página de introdução colocam deliberadamente um tom de brincadeira em primeiro plano, com frases como “monstrosity is beautiful” e “Certified unhinged™”
- O código-fonte do Hurl e do site é aberto, mas para enviar patches por e-mail é necessário ceder os direitos do patch
- A licença é oferecida em uma escolha entre AGPL-3.0, GAL-1.0 ou licença comercial
Um experimento de linguagem que deixou só o tratamento de exceções
- Hurl foi criada com um único propósito: investigar se é possível uma linguagem composta apenas por fluxo de controle baseado em tratamento de exceções
- A ideia veio de uma conversa entre Nicole Tietz-Sokolskaya e amigos do Recurse Center, cujas identidades não são divulgadas “por decoro”
- O site oferece documentação de uso do Hurl, exemplos, orientações de depuração e perguntas e respostas
Parece piada, mas é um projeto publicado de verdade
- A página de introdução traz depoimentos que revelam o caráter do Hurl
- “This monstrosity is beautiful, and I must never touch it”
- “Certified unhinged™!”
- “is "🤮" an available quote?”
- Para incluir depoimentos adicionais, é preciso enviar um e-mail a Nicole, com consentimento explícito para incluir a citação
Código-fonte e condições de licença
- O código-fonte da linguagem Hurl e deste site está publicado no repositório do Hurl
- Se encontrar bugs ou erros, você pode enviar patches por e-mail, mas precisa ceder todos os direitos sobre o patch
- É uma condição para manter a possibilidade de relicenciamento e de licenciamento comercial
- O projeto pode ser usado sob uma das três licenças a seguir
-
AGPL-3.0
- GAL-1.0: Gay Agenda License
- licença comercial
- No processo de análise das licenças, também foram consideradas licenças de brincadeira e licenças infelizes, mas no fim foram usadas as três licenças acima
-
1 comentários
Opiniões no Hacker News
Se eu fosse projetar uma linguagem de programação, forçaria namespaces em include/import e, se possível, também impediria efeitos colaterais no nível superior.
Receber algo como
let foo = include "lib/foo.hurl"e chamarfoo.init()é muito mais fácil de raciocinar.Por outro lado, se depois de
include "lib/foo.hurl" // side effectsaparecebaz(buz), fica difícil saber se a função e a variável são da biblioteca padrão ou se vieram de algum include em algum lugar.import "foo/bar"deveria permitir usarfoo.*oubar.*, nãobazz.*. Go vem logo à mente.O VSCode também faz algo parecido com plugins e LSP, mas é muito pior. A navegação pelo código é tão lenta que não consigo trabalhar com VSCode.
Fico me perguntando se esse tipo de proposta só é útil quando essas ferramentas não existem. Pelo menos em ambientes profissionais, parece impossível viver sem elas.
foo.init(), algo impossível com um import puro.Isso não quer dizer que o projeto não tenha valor; pelo contrário, eu o vejo como uma obra de arte.
Já fiz um fork de Ruby para que
requirenão sobrescrevesse a tabela de símbolos, mas o ecossistema Ruby parece depender demais de estado global mutável compartilhado, então acabei perdendo o interesse pelo próprio Ruby.Exceções sempre me pareceram ruins, porque dificultam entender o contrato entre chamador e chamado e também aumentam o acoplamento do código.
Prefiro a abordagem de tratar isso via valores de retorno, como em Go ou Rust. Ao passar os olhos pela linguagem, não ficou claro para mim se há algo que resolva esse problema.
Se uma IDE conseguisse descobrir dinamicamente todas as exceções não capturadas de uma função e permitir pular para os pontos onde exceções podem ser lançadas, esse modelo poderia ser aceitável. Mas não sei como o acoplamento seria tratado, e o grafo de fluxo de controle parece que ficaria extremamente instável.
Mas, em Java, a menos que a exceção herde de
RuntimeException, as exceções que uma função pode lançar fazem parte da assinatura da função. Nesse caso, se você lançar uma exceção sem adicioná-la à assinatura, o código não compila.As condições de Java tornam muito mais fácil para a IDE reportar exceções não capturadas, mas, no caso de exceções que não sejam de runtime, é um problema que dá para resolver com análise estática.
Por outro lado, retornar valores encapsulados padronizados
Ok/Errparece mais simples tanto para suporte de ferramentas quanto para conveniência dos desenvolvedores.A única diferença é que, no modelo de passar exceções adiante, você precisa escrever à mão o código repetitivo que o compilador escreveria por você.
Em 2024, não consigo entender por que alguém com a cabeça funcionando normalmente iria querer fazer isso à mão.
Durante o tempo em que usei, era muito mais doloroso encontrar a causa raiz sem um depurador.
O exemplo de
tossdiz que ele “é usado principalmente para passar vários valores para fora de uma função e não é estritamente necessário, mas é bonitinho”; isso não é inútil — é uma implementação de geradores retomáveis.Claro, se você quiser fazê-lo fazer outra coisa além de retomar imediatamente, pode ficar bem interessante. Basta estruturar toda a base de código como uma pilha de dentro-para-fora de
toss.returnprecisa estar lexicamente escopado ao handler.Por exemplo, em Python você pode chamar
next()de qualquer lugar.Isso está mais próximo de passar um callback por um canal lateral.
tosschama esse callback, ereturnliteralmente retorna dali.Em outra linguagem, seria um recurso realmente útil; aqui, tratá-lo como um recurso fofo e descartável parece até meio piada.
yieldem C#?Hurl parece bastante próximo de um sistema de condições no estilo Smalltalk ou Common Lisp.
Desenrolamento da pilha e retomada são apenas duas das reinicializações possíveis: https://gigamonkeys.com/book/beyond-exception-handling-condi...
Separado do projeto em si, acredito firmemente que o mundo seria um lugar melhor se mais coisas usassem a extensão .wtf em seus domínios.
Isso soa como uma forma fraca de efeitos algébricos, mas ainda é legal ver uma linguagem assim e o que se pode fazer com ela.
Se efeitos algébricos são basicamente algo como a palavra-chave
tossdo Hurl, fico curioso sobre em que ponto eles são mais poderosos quetoss.É um experimento mental interessante.
Eu realmente odeio exceções e quero uma linguagem sem elas.
Exceções são o
gotoda nossa era.Com
Maybe/OptioneEffect/Result, quase não há motivo para lançar exceções e precisar rastrear mentalmente onde elas são tratadas.Fico um pouco preocupado que efeitos algébricos fiquem mais populares e influenciem até o JS de frontend, que já é complexo demais, porque eles incentivam lançar “exceções” para controle de fluxo.
Se tudo isso é para evitar o problema das cores assíncrono/síncrono, pessoalmente acho que não vale nem um pouco a pena.
Uau, eu odeio isso. Mas, estranhamente, há algo quase elegante.
É muito difícil de modelar mentalmente, mas ainda assim.
Falando um pouco mais a sério, eu gostaria que houvesse sintaxes
catchdiferentes para exceções retomáveis e não retomáveis. Isso removeria a ambiguidade sintática sobre sereturndevolve ou não o fluxo de controle para o lado que lançou a exceção imediata mais próxima.E a biblioteca padrão não deveria fugir para funções comuns que retornam valores. Não é porque você experimentou a própria comida e teve azia que isso é motivo para não comê-la.
Entendi certo que coisas lançadas com
hurlpodem ser capturadas, mas coisas lançadas comtossnão podem? Vai levar um tempo para acostumar.Também me preocupa quanto Hurl eu vou precisar escrever até as pessoas começarem a me chamar de tosser.
Tosssoa como uma construção de linguagem interessante. Ela sobe pela pilha procurando um handler de exceção e depois volta ao ponto original, retomando a execução como se nada tivesse acontecido.Parece que essa construção permite injetar comportamento adicional em tempo de execução.
Normalmente, em código orientado a objetos, fazemos injeção de dependências por meio de construtores de serviços;
tosspermitiria isso por meio de “handlers de toss”?https://koka-lang.github.io/koka/doc/book.html#why-handlers
Não sei muito sobre ele, mas sei que permite injetar comportamento em runtime dessa forma.
Resume Nextdo VB.