1 pontos por GN⁺ 2023-08-09 | 1 comentários | Compartilhar no WhatsApp
  • Raku foi considerado como candidato a linguagem-calculadora para preencher lacunas no trabalho matemático deixadas por Python, J, Frink e Excel, e mesmo após experimentos curtos passou a impressão de ser uma linguagem muito poderosa, porém estranha
  • Tem ampla expressividade centrada em operadores, como símbolos Unicode, operadores infixos alfanuméricos, produto de listas, zip, reduce, acumulação, o matcher ~~ e sequências com ...
  • O usuário pode definir não só operadores infixos, mas também operadores circumfix/postcircumfix, e até a associatividade pode ser especificada além de esquerda e direita, incluindo encadeamento e lista
  • O despacho múltiplo faz ramificação não apenas por assinaturas de tipo, mas também por predicados de tempo de execução com where, e as assinaturas de função e até os parâmetros dentro delas podem ser tratados como valores de primeira classe
  • Parece exigir um custo alto para manter grandes bases de código, mas é atraente para programação em pequena escala, como scripts descartáveis, cálculos e ferramentas pessoais; os principais obstáculos são documentação, REPL no Windows, velocidade de compilação e erros com sigils

O que motivou olhar para Raku e a primeira impressão

  • Raku é a linguagem anteriormente conhecida como Perl 6
  • Depois de escrever reclamações sobre linguagens dinâmicas, alguns usuários recomendaram Raku, e fui conferir se ele serviria como linguagem-calculadora para tarefas matemáticas
  • Antes eu misturava Python, J, Frink e Excel, mas cada um tinha grandes desvantagens
  • A impressão após alguns dias de experimentos foi a de “uma linguagem projetada por gremlins realmente inteligentes, depois de coletar muito feedback de outros gremlins”

Um sistema de operadores incomum

  • Raku usa operadores Unicode de forma agressiva
    • Verificar pertencimento a conjunto é feito com
    • Também existem , e
  • Também permite operadores infixos alfanuméricos
    • O operador de repetição de string é x
    • Composição de função é o
  • Combinações de listas também são expressas com símbolos curtos
    • X cria o produto cartesiano de listas
    • Xf aplica f a cada elemento do produto cartesiano
    • Zf faz a mesma coisa no estilo zip
  • Para um operador infixo f, [f] faz o reduce da lista e [\\f] gera os resultados acumulados
    • [+] <1 2 3 4 5> é 15
    • [\\+] <1 2 3 4 5> é (1 3 6 10 15)

O matcher ~~ e as sequências ...

  • ~~ é usado como um matcher que trata vários tipos de comparação com uma única sintaxe
    • "abc" ~~ "abc" verifica igualdade de string
    • "abc" ~~ Str verifica se é do tipo string
    • "abc" ~~ {.chars == 3} verifica se o comprimento é 3
    • "abc" ~~ /^b/ verifica se abc começa com b
  • ... captura um padrão a partir dos valores anteriores para criar uma sequência
    • 0,1,2...10 cresce de 0 até 10 de 1 em 1
    • 0,2,4...10 vira uma sequência de números pares
    • 1,2,4...10 segue o padrão de crescimento, como 1 2 4 8

Operadores definidos pelo usuário

  • Raku não para em definir apenas operadores infixos, como algumas linguagens; também permite criar operadores circumfix e postcircumfix
  • Por exemplo, é possível definir um operador delimitador como sub circumfix:<[∀ zz>($inner){sum($inner)} para somar os valores internos
  • Também é possível definir um operador postcircumfix que parece um produto interno de vetores
    • sub postcircumfix:<| ⟩>(@left, @inside){[+] (@left Z* @inside)}
    • <1 2 3>|<4 5 6>⟩ é 32
  • A associatividade dos operadores também pode ser especificada de várias formas
    • Dá para definir operadores infixos normais associativos à esquerda ou à direita
    • É possível definir associatividade em cadeia, em que x < y < z é interpretado como x < y && y < z
    • Também há suporte a associatividade de lista, em que a op b op c vira op(a, b, c)

Despacho múltiplo e ramificação por condição em tempo de execução

  • Raku oferece despacho múltiplo, escolhendo a definição adequada entre várias funções com diferentes assinaturas de tipo
  • A função de exemplo f se comporta de forma diferente dependendo da combinação de argumentos
    • Se recebe um escalar e um array, soma o escalar a cada elemento do array
    • Também há suporte para o caso inverso, array e escalar
    • Se recebe dois arrays, soma elemento a elemento com Z+
  • O ponto mais peculiar é que também dá para despachar por predicados de tempo de execução do valor
    • multi my_abs(Int $x where {$x > 0}) {$x}
    • multi my_abs(Int $x) {-$x}
  • A assinatura de uma função é um valor de primeira classe, e os parâmetros dentro dela também são valores de primeira classe

Pequenos recursos que criam uma superfície ampla

  • Se você define uma função MAIN, seus parâmetros são convertidos automaticamente em flags de CLI
  • Os objetos têm um número enorme de métodos fornecidos de antemão
    • O objeto List object oferece métodos para obter todas as permutações, todas as k-combinações e todas as janelas deslizantes
  • Junctions são uma forma peculiar de valor para fazer várias comparações de uma vez
    • 1|2 se expande para any(1, 2), então 1 < 1|2 é verdadeiro
    • 1&2 se expande para all(1, 2), então 1 !< 1&2 é verdadeiro
  • Qualquer operador infixo pode receber ! na frente para virar um operador negado
  • Raku parece ser uma linguagem que tem nomes $kebab-case e subtração infixa ao mesmo tempo, e presume-se que o sigil é o que permite distinguir x-y
  • A regex syntax não é compatível com Perl 5
    • Durante 30 anos, as linguagens seguiram o “padrão” PCRE, mas Perl 6 abandonou isso

Áreas ainda não exploradas e o apelo em pequena escala

  • O que foi visto cobre apenas parte dos recursos, com foco no uso como calculadora
  • Ainda não explorei o sistema de objetos, pacotes nem grammars
  • Há muitos recursos que ficaram de fora, como samewith dentro do corpo da função, que parece servir para chamar a mesma função novamente com novos argumentos
  • Se eu tivesse de manter uma base legada em Raku, provavelmente seria muito difícil, mas para programação In The Small ele parece poderoso
    • scripts descartáveis
    • cálculos
    • ferramentas pessoais
    • o tipo de tarefa que eu queria desde o começo

Reclamações e expectativas

  • A documentação é muito fraca, e a dependência de símbolos dificulta as buscas
    • Mesmo tendo aprendido várias linguagens com documentação ruim, Raku é muito maior e mais complexo do que essas, o que pode desmotivar
  • No Windows, inserir Unicode no REPL faz tudo travar
  • O compilador também é bem lento; até arquivos pequenos levam mais de 0,5 segundo, e isso torna o trabalho iterativo doloroso
  • O sistema de sigils é incômodo
    • Houve um caso em que foram gastos 30 minutos depurando um problema por usar $x no lugar de @x
  • No geral, gosto de Raku e espero que dê certo, mas com o tempo torço para que o tempo de compilação e a documentação melhorem

1 comentários

 
GN⁺ 2023-08-09
Opiniões no Hacker News
  • Se colocássemos linguagens de programação em um espaço bidimensional, os eixos poderiam ser o quanto elas surpreendem e, quando surpreendem, se isso é prazeroso/terrível
    Existe uma expectativa implícita de que linguagens normais fiquem em geral no canto inferior esquerdo, “quase não surpreendem, mas, quando surpreendem às vezes, é de forma prazerosa”; Raku dá a impressão de mirar abertamente um canto superior esquerdo raramente ocupado. É uma postura mais próxima de “estranho, né? Não é legal?”

    • O problema é que esses eixos são subjetivos. Algo pode ser prazeroso e terrível; já escrevi JavaScript do tipo document.write = function ..., e foi prazeroso no sentido de que fez o que precisava fazer, mas ao mesmo tempo foi bem terrível
    • Quando tive que criar um parser para um trabalho da faculdade, descobri o recurso de grammar do Raku, e ele fazia quase tudo por mim, então parecia um cheat code, mas ainda assim foi divertido
    • Como originalmente era Perl 6, não surpreende que os desenvolvedores de Perl quisessem uma linguagem que não se parecesse em nada com outras linguagens
      Perl também tinha muitas “surpresas prazerosas”, e vejo o Raku como tendo sido projetado principalmente para eliminar as surpresas terríveis do Perl
    • Entendo o que querem dizer na parte em que verificam pertencimento a um conjunto com
      0,2,4...10 vira (0 2 4 6 8 10), mas 1,2,4...10 virar (1 2 4 8) faz pensar: “ele está procurando o próximo número na OEIS?”
    • Conforme os parágrafos avançavam, o Raku parecia ir cada vez mais para o canto superior direito, ou seja, a região do surpreendente e terrível
  • Raku é interessante como linguagem, mas alguns idiomas não entram muito bem na minha cabeça
    Parecido com o AppleScript, que tentava parecer linguagem natural e acabava soando estranho: ele mistura elementos com ar de linguagem natural como my, say, sub, gather com símbolos como @, declarações de módulos e outras decisões de sintaxe que, para quem vem de fora, parecem bizantinas. O exemplo do 99 bottles também dá para acompanhar logicamente, mas é difícil descobri-lo intuitivamente. Há muitos símbolos e a sensação de que eles são sobrecarregados dependendo do contexto; por isso, mesmo em tarefas para as quais o Raku poderia ser ideal, como um parser de linguagem natural, eu não teria vontade de usá-lo diretamente
    https://examples.raku.org/categories/module-management/Fletc...

    • Parece que você não mexeu com Perl. Com bagagem em Perl, boa parte dessa sintaxe, especialmente o sigil @ para arrays, parece bem familiar
    • Sinto exatamente a mesma coisa quando olho para Bash
  • Meu recurso favorito no Raku é que tanto a divisão inteira quanto literais decimais retornam Rat, um tipo racional
    Todo mundo sabe que ponto flutuante não é lá grande coisa, mas quase nenhuma linguagem tenta de fato sair disso; no Raku, só vira literal de ponto flutuante quando se usa notação científica

    • Linguagens mais antigas como Common Lisp e Scheme também estão esperando que pessoas que não gostam de ponto flutuante IEEE 754 as reconheçam
      Elas têm uma hierarquia numérica que inclui racionais e até racionais complexos, e naturalmente também dão suporte a números de precisão arbitrária. A capacidade de composição é excelente
    • Na prática, isso é quase um recurso ruim. Porque, se a representação de Rat fica grande demais, ela é automaticamente convertida para ponto flutuante
      1/10 é Rat, mas 1/100000000000000000000 vira Num. Também existe FatRat, que não é promovido, mas não é o padrão
    • A hierarquia numérica do Scheme lida corretamente com representações exatas há décadas
      Então, em vez de dizer que “ela se afastou do uso de ponto flutuante inexato mesmo quando ele não foi solicitado explicitamente”, o correto é ver que ela nunca esteve nesse estado para começo de conversa
    • Racket também diria algo diferente. Funciona corretamente
      (/ 1.0 3.0)0.3333333333333333, (/ 1 3)1/3, (- (+ 0.1 0.2) 0.3)5.551115123125783e-17
    • Não tenho certeza se isso é bom. Sei quando devo usar tipos decimal/racional e quando devo usar ponto flutuante, mas no meu código Python pessoal há muito mais chamadas a float() do que a Decimal()
      A menos que eu esteja lidando diretamente com dinheiro, ponto flutuante quase sempre é a escolha que quero
  • Não achei que a documentação do Raku fosse “realmente péssima”; pelo contrário, achei impressionante o site oficial de documentação ser um recurso centralizado que reúne tanto documentação conceitual quanto documentação de API
    https://docs.raku.org/
    Como ponto de partida para a documentação conceitual, esta página é excelente: https://docs.raku.org/language

    • Uso Raku há alguns anos, e a documentação é excelente e, ao mesmo tempo, insuficiente
      A maior parte do conteúdo existente é bem escrita e tem exemplos de código úteis, mas às vezes encontro partes que simplesmente não estão documentadas ou que cobrem apenas casos simples. O sistema de módulos, em especial, foi o maior problema; a distinção entre módulos e pacotes é difícil de entender lendo apenas a página Modules. O namespace importado e o namespace declarado podem ser diferentes, mas, para o compilador encontrá-los, a estrutura de diretórios precisa corresponder ao namespace; isso é útil e estranhamente faz sentido, mas tive que aprender mexendo diretamente
    • Isso vem da cultura Perl. O FAQ e as páginas de manual do Perl eram de altíssimo nível graças ao perfil dos programadores que usavam Perl: espirituosos, concisos e peculiares
    • As páginas de manual do Perl sempre foram excelentes
  • Todos os operadores Unicode legais do Raku têm notações alternativas em ASCII
    Por exemplo, as alternativas para , , , são (elem), !(elem), (cont), !(cont)
    https://docs.raku.org/language/unicode_ascii#Other_acceptabl...

    • Eu certamente usaria a versão ASCII
  • Parece que as críticas típicas feitas antes de conhecer bem a linguagem continuam se repetindo. Antes era o “line noise” do Perl; agora é algo como dizer que o Raku usa operadores Unicode sem cerimônia
    Mas isso é opcional, e eu mesmo testei para deixar o código mais compacto e expressivo na tela. Combina bem com um uso cuidadoso e criativo de Unicode. Também é comum a reação de não gostar de sigils, mas eu uso Raku/Perl 6 porque gosto da expressividade de “motosserra suíça” do Perl, e Raku parece Perl elevado ao quadrado, no melhor sentido. É mais organizado e expressivo, com uma pilha enorme de recursos sobre o bom e velho Perl. A documentação também é boa, embora ainda precise de manutenção constante; comparada à documentação do Perl, o padrão é muito alto

    • Fico curioso sobre como se digitam esses operadores não ASCII. Não sei se é um layout especial de teclado, se o editor converte automaticamente certas sequências, ou se usam escapes Unicode crus
      Fazer isso para economizar alguns caracteres parece complicado e pouco significativo
  • Às vezes eu me perguntava como seria uma linguagem de programação cheia de açúcar sintático, e agora eu sei
    A sensação é tipo “isso é horrível, mas estranhamente atraente, não consigo tirar os olhos, me mostre mais”

    • Talvez você goste de noulith, uma linguagem de hobby criada por uma pessoa que venceu vários Advent of Code recentes
      A descrição no GitHub diz: “slaps roof of [programming language]* this bad boy can fit so much [syntax sugar] into it.” Ela também venceu o Advent of Code mais recente usando essa linguagem: https://github.com/betaveros/noulith
    • Espere até conhecer as Grammars do Raku
    • Tenho a mesma reação toda vez que vejo C++ moderno
  • Vale lembrar que Raku começou originalmente como Perl 6, e que muita da filosofia de design veio do modo de pensar do Perl
    Pela reação imediata ao operador x para repetição de strings, parece que o autor não conhece bem a história do Perl e do Raku, mas isso existe no Perl há décadas

    • Como no texto há a frase “a sintaxe de regex não é retrocompatível com Perl 5. Durante 30 anos as linguagens seguiram o ‘padrão’ PCRE, e o Perl 6 simplesmente jogou tudo fora”, parece que ele sabe disso pelo menos em algum grau
    • A primeira nota de rodapé diz que Raku era conhecido anteriormente como Perl 6
    • O exagero de que “Perl6/Raku é completamente diferente de Perl 5” foi inflado demais
      Não foi chamado de Perl 6 à toa, e foi desenvolvido basicamente pela mesma equipe do Perl. Para quem usou bastante Perl 5, a herança em Perl6/Raku é evidente. Até o modelo de objetos inteiro do Raku parece mais uma versão um pouco mais poderosa do Moose.pm, um módulo Perl 5 do CPAN
  • Sinceramente, a sintaxe de regex do Perl 5/PCRE é horrível
    Ela existe apenas porque, na sintaxe antiga de regex, (? era um erro de sintaxe, então pôde ser redefinido para significar qualquer coisa. Raku é uma tentativa de projetar, do zero, uma linguagem de regex sensata agora que sabemos o que regexes deveriam expressar. A alternativa é ficar preso por mais 30 anos a coisas como (?:this|(?>or that))

    • Mais do que horrível, é magia negra indecifrável; quando você entende, fica incrível
      Faz tempo que não mexo com Perl, mas ainda uso regex com frequência
    • Concordo, mas é realmente útil
  • Em certo sentido, é definitivamente um gremlin. Gosto de ferramentas estranhas e complexas que aumentam a produtividade
    Mas não concordo com a comparação entre “programas grandes vs. programas pequenos”. Alguém menos prudente poderia interpretar isso como se fosse uma linguagem ruim para tarefas grandes, quando na prática ela pode ser tão boa quanto outras, ou até melhor. O problema, como em outras linguagens gremlin, é que é preciso sabedoria para usá-la bem. Por exemplo, quase ninguém que tenha usado bastante linguagens parecidas confunde $x com @x. Sigils, ao ler código, informam de imediato o tipo simples da variável — em Raku, a interface — e isso acaba ajudando; além disso, dá para usar de forma útil o mesmo namespace de variáveis com sigils diferentes. Parece estranho, parece um caractere desnecessário e você precisa saber o que significa, mas pode facilitar a vida: https://www.perl.com/article/on-sigils/
    O problema aparece para pessoas que não sabem muito bem o que estão fazendo. Para elas, essa linguagem gremlin pode ser um pesadelo vivo, exigindo muitos dispositivos de proteção como canaletas de boliche, boias de piscina, luvas de Kevlar, capacetes, GPS etc. Isso não quer dizer que não se possa construir um arranha-céu com uma linguagem gremlin; apenas que um não gremlin propenso a acidentes não consegue, enquanto um gremlin sábio consegue

    • Acho que a mentalidade de “esta ferramenta só pode ser usada por quem é bom o bastante” é um enorme cheiro de design ruim
      Ferramentas existem para ajudar a equipe a fazer o que precisa melhor ou mais rápido. Se você usa uma ferramenta desnecessariamente complexa para filtrar juniores ou alimentar o próprio ego, essa ferramenta vira mais uma arma contra o resto da organização do que uma ajuda