Raku, uma linguagem para gremlins
(buttondown.email)- 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∌
- Verificar pertencimento a conjunto é feito com
- Também permite operadores infixos alfanuméricos
- O operador de repetição de string é
x - Composição de função é
o
- O operador de repetição de string é
- Combinações de listas também são expressas com símbolos curtos
Xcria o produto cartesiano de listasXfaplicafa cada elemento do produto cartesianoZffaz 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" ~~ Strverifica se é do tipo string"abc" ~~ {.chars == 3}verifica se o comprimento é 3"abc" ~~ /^b/verifica seabccomeça comb
...captura um padrão a partir dos valores anteriores para criar uma sequência0,1,2...10cresce de0até10de 1 em 10,2,4...10vira uma sequência de números pares1,2,4...10segue o padrão de crescimento, como1 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 comox < y && y < z - Também há suporte a associatividade de lista, em que
a op b op cviraop(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
fse 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|2se expande paraany(1, 2), então1 < 1|2é verdadeiro1&2se expande paraall(1, 2), então1 !< 1&2é verdadeiro
- Qualquer operador infixo pode receber
!na frente para virar um operador negado - Raku parece ser uma linguagem que tem nomes
$kebab-casee subtração infixa ao mesmo tempo, e presume-se que o sigil é o que permite distinguirx-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
samewithdentro 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
$xno lugar de@x
- Houve um caso em que foram gastos 30 minutos depurando um problema por usar
- 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
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?”
document.write = function ..., e foi prazeroso no sentido de que fez o que precisava fazer, mas ao mesmo tempo foi bem terrívelPerl também tinha muitas “surpresas prazerosas”, e vejo o Raku como tendo sido projetado principalmente para eliminar as surpresas terríveis do Perl
∈0,2,4...10vira(0 2 4 6 8 10), mas1,2,4...10virar(1 2 4 8)faz pensar: “ele está procurando o próximo número na OEIS?”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,gathercom 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 diretamentehttps://examples.raku.org/categories/module-management/Fletc...
@para arrays, parece bem familiarMeu recurso favorito no Raku é que tanto a divisão inteira quanto literais decimais retornam
Rat, um tipo racionalTodo 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
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
Ratfica grande demais, ela é automaticamente convertida para ponto flutuante1/10éRat, mas1/100000000000000000000viraNum. Também existeFatRat, que não é promovido, mas não é o padrãoEntã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
(/ 1.0 3.0)dá0.3333333333333333,(/ 1 3)dá1/3,(- (+ 0.1 0.2) 0.3)dá5.551115123125783e-17float()do que aDecimal()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
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
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...
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
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”
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
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
xpara 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écadasNã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))Faz tempo que não mexo com Perl, mas ainda uso regex com frequência
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
$xcom@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
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