1 pontos por GN⁺ 3 시간 전 | 1 comentários | Compartilhar no WhatsApp
  • ClojureScript 1.12.145 teve o compilador alterado para gerar funções com a anotação ^:async como async function em JavaScript
  • Agora é possível escrever funções em ClojureScript que esperam valores Promise com await, melhorando a interoperabilidade com JavaScript
  • Também é possível usar ^:async em testes, validando com await o resultado de chamadas de funções assíncronas
  • Na pesquisa recente sobre Clojure, o suporte a async functions representou a maior fatia entre as solicitações de melhorias do ClojureScript relacionadas à interoperabilidade com JavaScript
  • Em casos comuns envolvendo APIs modernas de navegador e bibliotecas populares, diminui a necessidade de introduzir dependências adicionais, e a lista completa de mudanças pode ser consultada no item 1.12.145 do changelog do ClojureScript

Uso de ^:async e await

  • O ClojureScript 1.12.145 teve o compilador alterado para gerar funções com a anotação ^:async como JavaScript async function
  • Com o ClojureScript passando a ter como alvo o ECMAScript 2016, tornou-se possível escolher com mais cuidado as áreas de melhoria na interoperabilidade com JavaScript
  • Agora é possível escrever funções em ClojureScript que esperam valores Promise usando await
    (refer-global :only '[Promise])
    
    (defn ^:async foo [n]
      (let [x (await (Promise/resolve 10))
            y (let [y (await (Promise/resolve 20))]
                (inc y))
            ;; not async
            f (fn [] 20)]
        (+ n x y (f))))
    
  • Também é possível usar ^:async em testes, validando com await o resultado de chamadas de funções assíncronas
    (deftest ^:async defn-test
      (try
        (let [v (await (foo 10))]
          (is (= 61 v)))
        (let [v (await (apply foo [10]))]
          (is (= 61 v)))
        (catch :default _ (is false))))
    

Contexto e lista de mudanças

  • Na pesquisa recente sobre Clojure, o suporte a async functions representou a maior fatia entre as solicitações de melhorias do ClojureScript relacionadas à interoperabilidade com JavaScript
  • Com essa melhoria, em casos comuns envolvendo APIs modernas de navegador e bibliotecas populares, diminui a necessidade de introduzir dependências adicionais
  • A lista completa de correções, mudanças e melhorias pode ser consultada no item 1.12.145 do changelog do ClojureScript
  • O ClojureScript 1.12.145 contou com contribuição do membro da comunidade Michiel Borkent

1 comentários

 
GN⁺ 3 시간 전
Comentários do Hacker News
  • Vi que o borkdude postou este tópico e também aparece listado como contribuidor desta release
    Havia basicamente dois argumentos, repetidos há muito tempo, contra o suporte a async/await: que seriam necessárias mudanças profundas em todo o compilador de CLJS, e que macros de bibliotecas como Promesa já ofereciam uma conveniência parecida
    Também havia quem dissesse que bastava usar core.async, ou que uma linguagem orientada a expressões não combina bem com async/await, mas isso parecia mais opinião individual do que o argumento principal repetido nos fóruns
    No Slack dos Clojurians, o borkdude já tinha dito que não estava convencido de que adicionar suporte fosse inviável, e no fim parece que ele dedicou tempo e implementou mesmo, então sou muito grato

    • O Borkdude primeiro implementou async/await no Squint, sua implementação alternativa de ClojureScript, mostrando que era possível, e parece ter levado o que aprendeu ali para o compilador principal de CLJS
  • Um fato curioso é que o ClojureScript já suportava o paradigma assíncrono com a biblioteca core.async muito antes de o próprio JavaScript ganhar async/await
    Não estou tentando diminuir o valor desta release; só acho incrível poder usar um novo recurso de linguagem que ainda não existe na linguagem hospedeira apenas adicionando uma biblioteca às dependências. Clojure é sensacional

    • Com certeza. Usei bastante, funcionava bem e, apesar de algumas peculiaridades, na prática já tínhamos async/await havia mais de 10 anos
      Acho que descobri isso vendo uma palestra do David Nolen
      Depois disso, fui migrando para usar o mínimo possível de JavaScript no frontend, e SSE é lindo justamente por ser unidirecional. Fico feliz de ver desenvolvedores de várias comunidades de linguagem se interessando por SSE hoje em dia
      A palestra recente do David Nolen, “A ClojureScript Survival Kit”, também foi muito boa: https://youtu.be/BeE00vGC36E
      Nunca dá para agradecer o bastante pelo trabalho que David “Swannodette” Nolen fez desde o começo com ClojureScript e core.async. O que mais surpreende nessa palestra é que ele realmente parece empolgado com a ideia de abandonar o ClojureScript em favor de Clojure puro no servidor, eventos enviados pelo servidor e só um pouquinho de JavaScript
      A demo de fato começa por volta de 26:30. Ele mostra o uso de recursos de um webapp rodando no cliente e depois mostra o mesmo webapp rodando no servidor e sendo enviado ao cliente de forma unidirecional via SSE, com uso de recursos caindo quase a zero, o que é bem impactante
      Não serve para todos os casos, mas usando uma biblioteca mínima de manipulação de DOM ficou muito mais fácil raciocinar sobre o webapp e seu estado. Antes eu precisava manter tanto um REPL de Clojure quanto um REPL de ClojureScript, além de lidar com muito tráfego bidirecional e estados difíceis de reproduzir; agora tudo está bem mais rápido e mais fácil de reproduzir
    • Verdade, mas em 2026 também há muitos motivos para evitar core.async
      O output JavaScript fica maior, não há um modelo de erro embutido e, quando algo dá errado, ele é transformado em código de máquina de estados difícil de ler e depurar
      Além disso, a macro go não consegue transformar código fora da própria S-expressão, o que incentiva funções a ficarem grandes demais
      Como alguém da Cognitect disse, “core.async é uma bela bobagem”
  • É surpreendente ver Clojure/ClojureScript aparecendo com mais frequência nas redes ultimamente
    Usei no trabalho por alguns anos por volta de 2012, mas como muita gente acabei saindo da JVM e indo para linguagens funcionais tipadas
    Será que esse interesse renovado vem da programação com agentes? Será porque, sem verificação de tipos e com menos erros de sintaxe estranha ou palavras reservadas, fica mais rápido vasculhar código? Será que vem aí um renascimento das S-expressões?

    • No meu caso, fui de linguagens funcionais tipadas para ClojureScript e depois para Clojure, há cerca de 10 anos
      As bases de código sérias em Clojure que conheço investem bastante em suítes de teste, então basta acrescentar algumas técnicas para ensinar a IA a usar a suíte de testes da forma mais eficaz e ela consegue render muito bem
      Tenho colegas que fazem o agente interagir com o REPL, e dizem que isso é mais rápido por não pagar o custo de inicialização toda vez. Sou preguiçoso demais para ir tão longe, mas mesmo assim já é rápido o bastante
      Clojure tem poucos atritos. Tudo é verdadeiro exceto false e nil, não existe tabela de precedência de operadores, e a linguagem central dá suporte nativo a estruturas de dados imutáveis e persistentes
      Tudo é expressão, e não uma mistura de operadores e expressões. map, reduce e filter já vêm embutidos e são usados naturalmente no código comum
      Código Clojure escrito há 10 anos ainda tem grande chance de funcionar hoje, e o ecossistema e os designers da linguagem tratam quebrar código quase como um tabu
      Entre as linguagens que já usei, foi a mais livre para expressar ideias e a que menos me deu dor de cabeça. O Flowstorm, que é praticamente um depurador reverso, também é uma ferramenta dos sonhos para programar
      É uma linguagem excelente se você quer viver satisfeito. Por outro lado, a maioria dos usuários toma isso como algo natural e por isso não fala muito sobre isso
      Entre programadores que usam Clojure comercialmente, também há muitos que não entendem bem a linguagem e não são tão felizes. Muitas vezes não foi uma escolha deles, ou ainda não estavam prontos, e acho que antes de usar Clojure eles precisariam ter passado uns 10 anos sofrendo em outras linguagens com as coisas que detestavam nelas
      Os vídeos de Rich Hickey sobre software são famosos e influentes, mas isso não significa que meus colegas os tenham visto ou sequer se importem com eles
    • Acho que esse aumento recente de interesse tem muito a ver com o lançamento do documentário de Clojure: https://clojure.org/about/documentary
    • Outro recurso que combina bem com programação com agentes é o desenvolvimento guiado por REPL. Não sei por que essa abordagem não se espalhou mais em outras linguagens que teoricamente poderiam suportá-la
    • Já fiz programação com agentes em várias linguagens, e linguagens tipadas combinam muito melhor. O sistema de tipos praticamente corrige os erros alucinados pelo agente, especialmente em refatorações grandes
      Foi difícil lidar com uma base grande de Python sem tipos usando IA. Verificar se partes não cobertas por testes não quebraram é entediante demais
      Quanto mais forte o sistema de tipos, melhor. Além disso, os modelos de IA são treinados em código, então quanto mais popular a linguagem, maior a chance de desempenho melhor. ClojureScript é legal, mas não é linguagem dominante, então imagino que a IA vá performar pior do que em JavaScript
      No fim, se você está pensando em IA, é melhor escolher uma linguagem tipada ou, em uma linguagem dinâmica, pelo menos uma que tenha dicas de tipo
    • Lembro que saiu ou foi anunciado um documentário, então pode ser por isso
  • Isso é realmente grande. Desde o anúncio do Jank, não via tanta empolgação no ecossistema Clojure

  • Eu gostaria muito que alternativas ao JavaScript no frontend deixassem de ser obscuras e realmente se estabelecessem
    Queria experimentar algo como ClojureScript, mas é difícil imaginar onde eu usaria isso além de projetos pessoais paralelos. Talvez seja mais fácil adotar em uma organização cujo backend já seja Clojure

    • Fico curioso se a preocupação é por ser uma linguagem não dominante e os colegas não a conhecerem, ou se é medo de a linguagem em si ser abandonada ou ruim
      Nunca usei em produção, mas já coloquei no ar alguns side projects e coisas para a família. Reagent, o wrapper de React para ClojureScript, sinceramente fez mais sentido para mim do que o próprio React
      Você monta HTML com Hiccup, e componentes são apenas funções dentro de uma DSL de Hiccup, que na prática também é só uma lista, então o resultado fica muito elegante. O que é estático parece estático, o que é dinâmico parece claramente dinâmico, e tudo me pareceu ter bem menos mágica do que React comum
      O que achei ruim foi tentar usar componentes não funcionais encontrados no NPM. Não é fatal, mas o código fica feio. Dava para consertar com wrappers, mas algumas bibliotecas JS ficam bem bagunçadas por padrão no cljs
    • Não precisa ter medo, é realmente muito bom. Uso há 10 anos para compilar apps complexos em código cliente altamente otimizado e não chamaria isso de obscuro
      A comunidade também é muito gentil e madura
    • Em vez de só imaginar, basta começar pequeno. Se o seu time usa scripts bash, você pode reescrevê-los em Babashka
      Vale a pena começar convertendo scripts pessoais, pegar o jeito e sentir as vantagens. Não é melhor em todos os casos, mas, mais tarde, as pessoas podem vir pedir sua opinião, então você precisa estar bastante convencido
      Ao introduzir uma tecnologia desconhecida, uma boa estratégia é escolher algo menos importante, reescrever e deixar lá. Se der problema, é fácil voltar atrás; se as pessoas começarem a gostar, você vai ampliando aos poucos
      No passado, quando introduzi F# discretamente em uma organização .NET, comecei escrevendo em F# os testes menos importantes
    • Você deveria experimentar Gleam. Tenho usado em produção com muita satisfação
      https://blisswriter.app/
      https://blog.nestful.app/p/how-we-dropped-vue-for-gleam-and
    • Depois de ler https://hypermedia.systems/, cheguei à conclusão de que o melhor frontend é não ter frontend
  • Faz tempo que não acompanho cljs de perto, mas lembro que originalmente ele era apresentado mais ou menos como “Clojure sobre JavaScript”. Pelo menos tenho a impressão de que o Rich explicava assim no começo
    Entendi que a intenção era deixá-lo o mais próximo possível de mais um runtime
    Mas esta mudança parece adicionar um recurso que só existe em cljs, e await já é uma keyword de clojure.core, então isso também conflita com o próprio Clojure
    Fico me perguntando se as duas implementações foram se separando com o tempo, ou se esse recurso era importante o bastante para os usuários aceitarem essa diferença

  • Isso é importante porque permite lidar com interoperabilidade com JavaScript sem incluir bibliotecas adicionais
    Era um recurso que fazia falta há muito tempo, então esta release é muito bem-vinda

  • Parece melhor encapsular funções async/await em CSP. Clojure já tinha um padrão melhor

    • Esta release trata de expor ao ClojureScript recursos nativos da linguagem hospedeira
      core.async não vai desaparecer, e se async/await se encaixar melhor do que uma implementação baseada em Promise, a parte .cljs de core.async também pode ser atualizada
    • Você ainda pode fazer isso. No mundo de ClojureScript isso já era possível há vários anos; no fim das contas, tudo isso são apenas Promises
      Não acho que essa nova dica de função vá fazer esse caminho desaparecer
      https://clojurescript.org/guides/promise-interop#using-promi...
  • Não tenho muita certeza de como interpretar isso. Um dos pontos centrais de core.async não era justamente empurrar tudo isso para canais?
    Não sei se ter uma keyword async ao estilo JavaScript é realmente um upgrade

    • Isso serve para usar recursos de JS sem trazer dependências extras como core.async
      Não é obrigatório usar, e você ainda pode continuar usando core.async. Inclusive foi o recurso mais pedido na pesquisa recente do ClojureScript.