Raku, un langage pour les gremlins
(buttondown.email)- Raku a été envisagé comme candidat au titre de langage-calculatrice pour combler les lacunes de Python, J, Frink et Excel dans les tâches mathématiques, et même après une courte expérimentation, il donne l’impression d’être un langage très puissant mais étrange
- Son expressivité centrée sur les opérateurs est vaste, avec des symboles Unicode, des opérateurs infix alphanumériques, le produit de listes, le zip, le reduce, l’accumulation, le matcher
~~et les séquences... - L’utilisateur peut définir non seulement des opérateurs infix, mais aussi des opérateurs circumfix/postcircumfix, et spécifier leur associativité au-delà du simple gauche/droite, jusqu’aux associations en chaîne ou en liste
- Le multiple dispatch ne se limite pas aux signatures de type : il peut aussi bifurquer selon des prédicats d’exécution
where, et les signatures de fonctions comme leurs paramètres sont traités comme des valeurs de premier ordre - Cela semble lourd à maintenir dans une grande base de code, mais reste séduisant pour de la programmation à petite échelle comme les scripts jetables, les calculs ou les outils personnels ; la documentation, le REPL Windows, la vitesse de compilation et les erreurs de sigils sont les principaux freins
Pourquoi regarder Raku, et première impression
- Raku est le langage autrefois connu sous le nom de Perl 6
- Après avoir écrit sur mes frustrations envers les langages dynamiques, plusieurs personnes m’ont recommandé Raku, et je l’ai examiné pour voir s’il convenait comme langage-calculatrice pour des tâches mathématiques
- Jusqu’ici, j’utilisais un mélange de Python, J, Frink et Excel, mais chacun avait de gros défauts
- Après quelques jours d’expérimentation, mon impression se rapprochait de ceci : « un langage conçu par des gremlins vraiment brillants, ayant beaucoup intégré les retours d’autres gremlins »
Un système d’opérateurs inhabituel
- Raku utilise activement des opérateurs Unicode
- l’appartenance à un ensemble se vérifie avec
∈ - il existe aussi
∉,∋et∌
- l’appartenance à un ensemble se vérifie avec
- Il autorise aussi les opérateurs infix alphanumériques
- l’opérateur de répétition de chaîne est
x - la composition de fonctions est
o
- l’opérateur de répétition de chaîne est
- Les combinaisons de listes s’expriment également avec une notation courte
Xproduit le produit cartésien de listesXfappliquefà chaque élément du produit cartésienZffait la même chose en mode zip
- Pour un opérateur infix
f,[f]réduit une liste et[\\f]produit les résultats cumulés[+] <1 2 3 4 5>vaut15[\\+] <1 2 3 4 5>vaut(1 3 6 10 15)
Le matcher ~~ et les séquences ...
~~sert de matcher unifié pour plusieurs types de comparaison"abc" ~~ "abc"vérifie l’égalité de chaînes"abc" ~~ Strvérifie qu’il s’agit du type chaîne"abc" ~~ {.chars == 3}vérifie que la longueur est de 3"abc" ~~ /^b/vérifie siabccommence parb
...construit des séquences en déduisant un motif à partir des valeurs précédentes0,1,2...10augmente de 1 de0à100,2,4...10produit une séquence de nombres pairs1,2,4...10suit un motif de croissance comme1 2 4 8
Opérateurs définis par l’utilisateur
- Raku ne se contente pas, comme certains langages, de laisser définir des opérateurs infix : il permet aussi de créer des opérateurs circumfix et postcircumfix
- Par exemple,
sub circumfix:<[∀ zz>($inner){sum($inner)}permet de définir un opérateur englobant qui additionne les valeurs internes - Il est également possible de définir un opérateur postcircumfix qui ressemble à un produit scalaire de vecteurs
sub postcircumfix:<| ⟩>(@left, @inside){[+] (@left Z* @inside)}<1 2 3>|<4 5 6>⟩vaut32
- L’associativité des opérateurs peut aussi être configurée de nombreuses façons
- on peut définir des opérateurs infix classiques associatifs à gauche ou à droite
- on peut spécifier une association en chaîne où
x < y < zest interprété commex < y && y < z - une association en liste est aussi prise en charge, où
a op b op cdevientop(a, b, c)
Multiple dispatch et branchement sur conditions d’exécution
- Raku prend en charge le multiple dispatch, qui choisit parmi plusieurs définitions d’une fonction selon leurs signatures de types
- Dans l’exemple de la fonction
f, le comportement change selon la combinaison des arguments- avec un scalaire et un tableau, elle ajoute le scalaire à chaque élément du tableau
- le cas tableau puis scalaire est également pris en charge
- avec deux tableaux, elle additionne les éléments correspondants avec
Z+
- Plus inhabituel encore, le dispatch peut aussi se faire à partir de prédicats évalués à l’exécution
multi my_abs(Int $x where {$x > 0}) {$x}multi my_abs(Int $x) {-$x}
- Les signatures de fonctions sont des valeurs de premier ordre, et les paramètres qu’elles contiennent le sont aussi
Une large surface créée par une foule de petites fonctionnalités
- Si l’on définit une fonction
MAIN, ses paramètres sont automatiquement transformés en flags CLI - Les objets disposent d’un très grand nombre de méthodes fournies d’avance
- List object fournit des méthodes pour obtenir toutes les permutations, toutes les k-combinaisons et toutes les fenêtres glissantes
- Les Junctions sont une forme de valeur inhabituelle permettant d’effectuer plusieurs comparaisons à la fois
1|2s’étend enany(1, 2), ce qui fait que1 < 1|2est vrai1&2s’étend enall(1, 2), ce qui fait que1 !< 1&2est vrai
- N’importe quel opérateur infix peut être précédé de
!pour devenir un opérateur de négation - Raku semble être un langage qui possède à la fois des noms comme
$kebab-caseet une soustraction infix, vraisemblablement parce que les sigils permettent de distinguerx-y - La syntaxe des regex n’est pas rétrocompatible avec Perl 5
- alors que les langages ont suivi pendant 30 ans le « standard » PCRE, Perl 6 a choisi de l’abandonner
Domaines encore inexplorés et attrait à petite échelle
- Ce qui a été examiné ici ne représente qu’une partie des fonctionnalités, surtout du point de vue de l’usage calculatrice
- Le système objet, les packages et les grammaires n’ont pas encore été étudiés
- Il manque aussi beaucoup d’éléments, comme
samewith, qui permet apparemment de réappeler la même fonction avec de nouveaux arguments depuis son corps - Si je devais maintenir une base de code legacy en Raku, cela me semblerait très difficile, mais pour la programmation In The Small, le langage paraît puissant
- scripts jetables
- calculs
- outils personnels
- le type de tâches que je cherchais au départ
Frustrations et attentes
- La documentation est très insuffisante, et la forte dépendance aux symboles rend la recherche difficile
- même avec de l’expérience dans l’apprentissage de langages mal documentés, Raku est bien plus vaste et complexe, ce qui peut faire tomber la motivation
- Sous Windows, saisir de l’Unicode dans le REPL provoque un crash
- Le compilateur est aussi assez lent : même un petit fichier demande plus de 0,5 seconde, ce qui rend les itérations pénibles
- Le système de sigils est peu pratique
- il y a eu un cas où 30 minutes ont été perdues à déboguer un problème causé par l’usage de
$xau lieu de@x
- il y a eu un cas où 30 minutes ont été perdues à déboguer un problème causé par l’usage de
- Globalement, j’aime bien Raku et j’espère qu’il réussira, mais j’espère aussi qu’avec le temps, les temps de compilation et la documentation s’amélioreront
1 commentaires
Avis sur Hacker News
Si l’on plaçait les langages de programmation dans un espace à deux dimensions, les axes pourraient être à quel point ils surprennent et, quand ils surprennent, si c’est agréable ou horrible.
On s’attend implicitement à ce qu’un langage normal se situe plutôt en bas à gauche, « surprend peu, mais quand il surprend parfois, c’est agréable ». Raku donne l’impression de viser ouvertement le quadrant supérieur gauche, rarement occupé : une attitude du genre « c’est bizarre, non ? Ce n’est pas génial ? »
document.write = function ..., et c’était agréable parce que ça faisait ce qu’il fallait, mais en même temps assez horrible.Perl avait aussi beaucoup de « surprises agréables », et je vois surtout Raku comme une conception visant à éliminer les surprises horribles de Perl.
∈me fait comprendre l’idée.0,2,4...10donne(0 2 4 6 8 10), mais quand1,2,4...10donne(1 2 4 8), on se demande : « il va chercher le terme suivant dans l’OEIS ? »Raku est intéressant comme langage, mais certains idiomes ne me rentrent pas bien dans la tête.
Un peu comme AppleScript, qui essayait de ressembler au langage naturel et finissait par paraître étrange, Raku mélange des éléments à allure de langage naturel comme
my,say,sub,gather, des symboles comme@, des déclarations de modules, et d’autres choix syntaxiques qui paraissent byzantins à un regard extérieur. Même l’exemple 99 bottles se suit logiquement, mais il est difficile à découvrir intuitivement. Il y a beaucoup de symboles, surchargés selon le contexte, au point que même pour des tâches où Raku pourrait être optimal, comme un parseur de langage naturel, je n’aurais pas envie de l’utiliser directement.https://examples.raku.org/categories/module-management/Fletc...
@pour les tableaux, paraît assez familière.Ma fonctionnalité préférée dans Raku, c’est que la division entière comme les littéraux décimaux renvoient tous deux
Rat, un type rationnel.Tout le monde sait que les nombres à virgule flottante ne sont pas terribles, mais peu de langages essaient vraiment de s’en éloigner ; avec Raku, il faut utiliser la notation scientifique pour obtenir un littéral flottant.
Ils disposent d’une hiérarchie numérique qui inclut les rationnels et même les rationnels complexes, et prennent évidemment en charge les nombres à précision arbitraire. La composabilité est excellente.
Ratdevient trop grande, elle est automatiquement convertie en virgule flottante.1/10est unRat, mais1/100000000000000000000devient unNum. Il existe aussiFatRat, qui n’est pas promu, mais ce n’est pas le comportement par défaut.Il vaut donc mieux dire qu’elle n’a jamais été dans une situation où elle « s’est éloignée d’une façon d’utiliser des flottants inexacts sans qu’on les ait explicitement demandés ».
(/ 1.0 3.0)donne0.3333333333333333,(/ 1 3)donne1/3, et(- (+ 0.1 0.2) 0.3)donne5.551115123125783e-17.float()queDecimal().Sauf quand on manipule directement de l’argent, les flottants sont presque toujours le choix souhaité.
Je n’ai pas trouvé la documentation de Raku « vraiment épouvantable » ; au contraire, le site officiel m’a impressionné comme ressource tout-en-un regroupant à la fois la documentation conceptuelle et la documentation d’API.
https://docs.raku.org/
Comme point de départ pour la documentation conceptuelle, cette page est excellente : https://docs.raku.org/language
La plupart de ce qui existe est bien écrit et contient des exemples de code utiles, mais il m’arrive de tomber sur des parties pas du tout documentées ou ne couvrant que des cas simples. Le système de modules a été le plus problématique : la distinction modules/packages est difficile à comprendre en lisant seulement la page Modules. Les espaces de noms importés et les espaces de noms déclarés peuvent être différents, mais pour que le compilateur les trouve, la structure de répertoires doit correspondre à l’espace de noms ; c’est utile et étrangement logique, mais j’ai dû l’apprendre en expérimentant.
Les superbes opérateurs Unicode de Raku ont tous une notation de substitution ASCII.
Par exemple, les substituts de
∈,∉,∋,∌sont(elem),!(elem),(cont),!(cont).https://docs.raku.org/language/unicode_ascii#Other_acceptabl...
On dirait que les critiques typiques formulées avant même de bien connaître le langage se répètent encore. Avant, c’était le « bruit de ligne » de Perl ; maintenant, c’est que Raku utilise sans complexe des opérateurs Unicode
Mais c’est optionnel, et j’ai essayé de les utiliser directement pour rendre le code plus compact et expressif à l’écran. Ça se prête bien à une utilisation réfléchie et créative d’Unicode. La réaction de rejet envers les sigils est aussi courante, mais j’aimais l’expressivité de Perl, ce côté couteau suisse à moteur, et c’est pour ça que j’ai utilisé Raku/Perl 6 ; Raku donne l’impression d’être Perl élevé au carré, dans ce qui fait Perl. C’est mieux structuré, très expressif, et un énorme tas de fonctionnalités a été empilé sur le bon vieux Perl. La documentation est bonne aussi, même si elle doit continuer à être entretenue, et la comparaison avec la doc de Perl place la barre très haut
Faire ça pour économiser quelques caractères me paraît compliqué et pas très utile
Je me suis parfois demandé à quoi ressemblerait un langage de programmation rempli de sucre syntaxique, maintenant je le sais
C’est du genre « c’est horrible, mais étrangement attirant, impossible de détourner le regard, montrez-m’en encore »
La présentation GitHub dit : « slaps roof of [programming language]* this bad boy can fit so much [syntax sugar] into it. » Il a aussi gagné le plus récent Advent of Code en utilisant ce langage : https://github.com/betaveros/noulith
Il vaut la peine de rappeler que Raku a commencé comme Perl 6, et qu’une grande partie de sa philosophie de conception vient de la façon de penser de Perl
À voir la réaction immédiate de l’auteur à l’opérateur
xpour répéter des chaînes, on dirait qu’il ne connaît pas bien l’histoire de Perl et de Raku, alors que Perl fait ça depuis des décenniesCe n’est pas pour rien qu’il s’appelait Perl 6, et il a été développé par à peu près la même équipe Perl. Pour quelqu’un qui a pas mal utilisé Perl 5, l’héritage de Perl6/Raku est évident. Même tout le modèle objet de Raku ressemble beaucoup à une version un peu plus puissante de Moose.pm, un module Perl 5 de CPAN
Franchement, la syntaxe des regex Perl 5/PCRE est horrible
La seule raison pour laquelle elle existe, c’est que
(?était une erreur de syntaxe dans l’ancienne syntaxe des regex, donc on pouvait le redéfinir pour n’importe quoi. Raku est une tentative de concevoir dès le départ un langage de regex sensé, maintenant qu’on sait ce que les expressions régulières doivent exprimer. L’alternative, c’est de rester coincé pendant 30 ans de plus avec des choses comme(?:this|(?>or that))Ça fait longtemps que je n’ai pas touché à Perl, mais j’utilise encore souvent les regex
Dans un certain sens, c’est clairement un gremlin. J’aime les outils bizarres et complexes qui augmentent la productivité
En revanche, je ne suis pas d’accord avec la comparaison « grands programmes vs petits programmes ». Quelqu’un de moins avisé pourrait comprendre que c’est un mauvais langage pour les gros travaux, alors qu’en réalité il peut être aussi bon, voire meilleur, que d’autres langages. Le problème, comme avec les autres langages gremlins, c’est qu’il faut de la sagesse pour bien s’en servir. Par exemple, les gens qui confondent
$xet@xsont rares parmi ceux qui ont suffisamment utilisé des langages similaires. Les sigils rendent même la lecture du code plus facile, parce qu’ils indiquent immédiatement le type simple d’une variable, ou dans Raku son interface, et permettent d’utiliser utilement le même espace de noms de variables avec différents sigils. Ça paraît étrange, ça ressemble à des caractères inutiles, et il faut en connaître le sens, mais cela peut simplifier la vie : https://www.perl.com/article/on-sigils/Les problèmes apparaissent avec les gens qui ne savent pas vraiment ce qu’ils font. Pour eux, ce langage gremlin peut être un cauchemar éveillé, et ils ont besoin de beaucoup de protections : pare-chocs de bowling, bouées, gants en Kevlar, casque, GPS. Cela ne veut pas dire qu’on ne peut pas construire un gratte-ciel avec un langage gremlin ; seulement qu’un non-gremlin prompt aux accidents ne le peut pas, alors qu’un gremlin avisé, lui, le peut
Les outils existent pour aider une équipe à mieux ou plus vite accomplir ce dont elle a besoin. Si l’on utilise un outil inutilement complexe pour filtrer les juniors ou flatter son ego, cet outil tient plus de l’arme que de l’aide pour le reste de l’organisation