IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langages de programmation Discussion :

Noulith : un nouveau langage de programmation construit sur Rust


Sujet :

Langages de programmation

  1. #1
    Chroniqueur Actualités
    Avatar de Bruno
    Homme Profil pro
    Rédacteur technique
    Inscrit en
    mai 2019
    Messages
    1 215
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Cameroun

    Informations professionnelles :
    Activité : Rédacteur technique
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : mai 2019
    Messages : 1 215
    Points : 24 368
    Points
    24 368
    Par défaut Noulith : un nouveau langage de programmation construit sur Rust
    Noulith : un nouveau langage de programmation construit sur Rust,
    il permettrait de générer des résultats sans erreur avec n'importe quelle syntaxe

    Brian Chen, ingénieur logiciel en sécurité chez Zoom, a créé un nouveau langage de programmation appelé Noulith. Construit sur Rust, Chen s'est inspiré de l'ouvrage « Crafting Interpreters » de Robert Nystrom. Parmi ses collaborateurs clés, on trouve : Gustav Westling et Dmitry Cheryasov. Ce nouveau langage de programmation a fait l'objet d'une grande attention sur Internet en raison de sa caractéristique principale, qui serait de donner « des résultats corrects ». Quelle que soit votre syntaxe, Noulith prétend donner des résultats exacts.

    Les structures de données immuables (mais pas les variables) signifient qu’il est possible d’écrire matrix = [[0] ** 10] ** 10 ; matrix[1][2] = 3 et ne pas s'en inquiéter, au lieu de [[0] * 10 for _ in range(10)] que le langage Python impose par exemple à ses utilisateurs. Il est également possible d’utiliser librement des éléments comme clés dans les dictionnaires.

    Nom : developpeurs.jpg
Affichages : 26229
Taille : 33,3 Ko

    Mais, grâce aux manœuvres de mutation ou de copie à l'écriture en interne (alimentées par les pointeurs de comptage de référence surpuissants de Rust), le programmeur n'a pas à sacrifier les performances qu’il obtiendra en mutant des listes. Tout est un opérateur infixe ; presque tout peut être appliqué partiellement. Si vous pensiez que Scala avait beaucoup de souplesse syntaxique, attendez de voir ce que nous avons.

    Noulith > 1 à 10 filter even map (3*)

    [6, 12, 18, 24, 30]


    Vous avez déjà voulu écrire x max= y en cherchant une valeur maximale dans une boucle compliquée ? Vous pouvez le faire avec Noulith. Ceci est possible avec n'importe quelle fonction.

    « Vous savez que Python a ce cas limite où vous pouvez écrire des choses comme {1} et {1, 2} pour obtenir des ensembles, mais {} est un dictionnaire parce que les dictionnaires sont arrivés en premier ? Nous n'avons pas ce problème car nous ne distinguons pas les ensembles et les dictionnaires. »

    La précédence des opérateurs est personnalisable et résolue au moment de l'exécution.

    noulith> f := \-> 2 + 5 * 3

    noulith> f()
    17

    noulith> swap +, *

    noulith> f() # (2 times 5) plus 3
    13
    noulith> swap +["precedence"], *["precedence"]

    noulith> f() # 2 times (5 plus 3)
    16

    noulith> swap +, *
    noulith> f() # (2 plus 5) times 3
    21


    Imaginez tout le code d'analyse des opérateurs que vous n'aurez pas à écrire. Lorsque vous avez besoin d'un nombre arbitraire de niveaux de précédence d'opérateurs, et que vous êtes heureux d'évaluer les entrées.

    Exécution du code Noulith

    C'est un projet Rust standard, donc, en bref :

    Installer Rust et le configurer
    Clonez ce dépôt,
    cargo run --release --features cli,request, crypto
    Ceci vous amènera dans un REPL, ou vous pouvez passer un nom de fichier pour l'exécuter. Si vous voulez juste construire un exécutable pour pouvoir rénommer ou l'ajouter à $PATH, exécutez simplement cargo build --release --features cli,request,crypto et regardez dans target/release.
    Aucune des options de la ligne de commande pour cargo run ou cargo build n'est nécessaire ; elles donneraient juste de meilleures performances d'exécution et des fonctionnalités pour un temps de compilation plus lent et une taille binaire plus importante. (Sans --release, les frames de pile sont si grands qu'un des tests fait déborder la pile...)

    Quelques Fonctionnalités

    • Typé dynamiquement ;
    • Les listes et les dictionnaires devraient semblent ressembler à Python. Les listes sont des parenthèses : [a, b, c]. Les dictionnaires sont des accolades : {a, b, c}. Noulith ne prend pas la peine de créer un type d'ensemble distinct, « les dictionnaires se comportant souvent comme leurs ensembles de clés » ;
    • Au plus haut niveau, les instructions sont de type C/Java/ if (condition) body else body, for (thing) body (pas le moderne if cond { body })Le if ... else est l'expression ternaire ;
    • Les boucles For utilisent les flèches de gauche : for (x <- xs) .... Utilisez une flèche à double tête pour les paires indice-valeur ou clé-valeur : for (i, x <<- xs) ;
    • Les lambdas se présentent comme suit : x, y -> x + y
    • Pas sensible à l'espacement ou à l'indentation. Selon chien, les symboles des opérateurs peuvent être enchaînés librement comme en Haskell ou Scala.

    Rappelons que Scala est un langage de programmation polyvalent à typage statique qui prend en charge la programmation orientée objet et la programmation fonctionnelle. Conçu pour être concis, Scala avec ses nombreuses décisions de conception vise à répondre aux critiques de Java. La version 3 du langage est une refonte complète du langage Scala.

    Exemple

    Quelque peu impératif :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    for (x <- 1 to 100) (
      o := '';
      for (f, s <- [[3, 'Fizz'], [5, 'Buzz']])
        if (x % f == 0)
          o $= s;
      print(if (o == '') x else o)
    )

    Quelque peu fonctionnel :

    for (x <- 1 to 100) print([[3, 'Fizz'], [5, 'Buzz']] map (\(f, s) -> if (x % f == 0) s else "") join "" or x)
    Les nombres, les opérateurs arithmétiques et les comparaisons
    Les nombres, les opérateurs arithmétiques et les comparaisons fonctionnent pour la plupart comme vous vous y attendez, y compris les opérateurs bit à bit de style C, sauf que :
    ^ est une exponentiation. À la place, ~ en tant qu'opérateur binaire est xor (mais peut toujours être unaire en tant que complément binaire). Ou vous pouvez simplement utiliser xor.

    / fait une division rationnelle parfaite comme dans Common Lisp ou autre. % fait un modulo signé de style C. // fait la division entière en arrondissant à l'inférieur, et %% fait le modulo apparié (Deux élements E1 et E2 sont dit appariés lorsque chaque valeur x1,i de E1 est associée à une valeur x2,i de E2).

    La précédence

    La précédence est quelque chose d'un peu raisonnable et plus simple, inspiré par la précédence de Go.

    Go est un langage de programmation open source, développé par Google, qui facilite le développement de logiciels simples, fiables et efficaces. En raison de sa simplicité, il est utilisé aussi bien pour développer des applications, écrire des scripts pour de grands systèmes. Cette simplicité est nécessaire aussi pour assurer la maintenance et l'évolution des programmes sur plusieurs générations de développeurs.

    S'il vise aussi la rapidité d'exécution, indispensable à la programmation système, il considère le multithreading comme le moyen le plus robuste d'assurer sur les processeurs actuels, cette rapidité tout en rendant la maintenance facile par séparation de tâches simples exécutées indépendamment. Cette conception permet également le fonctionnement sans réécriture sur des architectures multicœurs en exploitant immédiatement l'augmentation de puissance correspondante.

    Plutôt que de suivre l'héritage du C, Noulith suit l’exemple du langage Go :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Tighter ^ << >>
            * / % &
            + - ~
            |
    Looser  == != < > <= >=

    Comme en Python et en mathématiques, les opérateurs de comparaison peuvent être enchaînés comme 1< 2 < 3. Noulith possède également min, max, et l'opérateur de comparaison à trois valeurs <=> et son inverse >=<.

    Les chaînes de caractères : comme en Python, Noulith n'a pas de type de caractère séparé ; l'itération sur une chaîne de caractères ne donne que des chaînes à un seul caractère.
    Types de données :

    • Null ;
    • Nombres : grands nombres entiers, rationnels, flottants et complexes, qui coagissent de gauche à droite dans une liste selon les besoins. Notons qu'il n'y a pas de booléens, à la place, 0 et 1 sont utilisés ;
    • Listes (hétérogènes) : [a, b]. Indexation et découpage à la fois dans la syntaxe et la sémantique des entiers négatifs ;
    • Dictionnaires (hétérogènes) : {a : b, c : d}. Les valeurs peuvent être omises, dans ce cas, elles sont juste nulles, et sont utilisées comme des ensembles. Index my_dict[key], test key in my_dict. Si vous ajoutez un {:a}, c'est la valeur par défaut ;
    • Chaînes de caractères : juste ce que Rust a, toujours des séquences d'octets UTF-8 valides ;
    • Octets ;
    • Vecteurs : listes de nombres, remarquables par le fait que la plupart des opérations sur ceux-ci se diffusent automatiquement, par exemple V(2, 3) + V(4, 5) == V(6, 8) ; V(2, 3) + 4 == V(6, 7) ;
    • Streams : listes non dynamiques, générées uniquement dans quelques situations spécifiques pour le moment.

    Les expressions

    Tout est une fonction globale et peut être utilisé comme un opérateur ! Par exemple, a + b est simplement +(a, b) ; a max b est max(a, b). Dans un cas particulier, a b (lorsqu'il est entouré d'une autre syntaxe qui empêche de traiter l'un ou l'autre comme un opérateur binaire) est a(b) (ceci est principalement pour permettre le moins unaire), mais quatre identificateurs ou plus de taille égale et des élements similaires dans une rangée comme (a b c d) est illégal. (Aussi, faites attention au fait que a[b] est analysé comme indexant b dans a, et non pas a([b]).

    De même : de nombreuses fonctions/opérateurs qui acceptent normalement deux arguments n'en acceptent qu'un seul et l'appliquent partiellement comme leur second, par exemple +(3) (qui, comme ci-dessus, peut être écrit +3 dans le bon contexte) est une fonction qui ajoute 3. (Ce n'est pas une syntaxe spéciale, juste une option de nombreuses fonctions ; + est défini pour prendre un ou deux arguments et s'il en prend un, il s'applique partiellement). Puisque - et ~ ont des surcharges unaires, Noulith fournit des alternatives comme subtract et xor qui s'appliquent partiellement lorsqu'elles sont appelées avec un argument, tout comme en Haskell.

    Haskell est un langage de programmation fonctionnel fondé sur le lambda-calcul et la logique combinatoire. Son nom vient du mathématicien et logicien Haskell Curry. Il a été créé en 1990 par un comité de chercheurs en théorie des langages intéressés par les langages fonctionnels et l'évaluation paresseuse. Si vous appelez a(b) où a n'est pas une fonction mais b l'est, b applique partiellement a comme premier argument. C'est exactement comme les sections en Haskell.

    Les identificateurs peuvent être constitués d'une lettre ou d'un _ suivi de n'importe quel nombre de caractères alphanumériques, de ', ou de ? ; ou de n'importe quel nombre consécutif de symboles valides pour être utilisés dans des opérateurs, y compris ? (Ainsi, par exemple, a*-1 ne fonctionnera pas parce que *- sera interprété comme un seul jeton. a* -1 ne fonctionnera pas non plus, mais pour une raison différente - il est interprété comme s'il commençait par appeler * avec a et - comme arguments.

    a*(-1) ou a* -(1) fonctionneraient). Par rapport à des langages similaires, notons que : n'est pas un caractère légal à utiliser dans les opérateurs, alors que $ l'est. De plus, un certain nombre de mots-clés sont interdits, ainsi que toutes les lettres majuscules et tous les éléments commençant par des lettres majuscules suivies d'un guillemet simple (bien que ceux-ci soient réservés et que le langage ne les reconnaisse pas encore tous) ; =, !, ..., <-, ->, et <<-. De plus, à l'exception de == != <= et >=, les opérateurs se terminant par = seront interprétés comme l'opérateur suivi d'un =, donc en général les opérateurs ne peuvent pas se terminer par =.

    Variables et affectations

    Déclarez avec :=, assignez avec =. (Les déclarations doivent être séparées par des points-virgules).
    x := 0; x = 1
    En fait, := est juste une déclaration avec un type vide. Les variables typées peuvent être déclarées comme :
    x : int = 3
    Les séquences peuvent être décomposées à l'aide de virgules, y compris une virgule de fin pour la décomposition d'un seul élément. Les annotations de type sont plus souples que les virgules, ainsi, ci-dessous, x et y sont tous deux des ints. Préfixe ... pour empaqueter/dépaqueter plusieurs éléments, et de même dans les appels de fonction.
    x, y : int
    Il est possible de déclarer dans une affectation avec une annotation entre parenthèses.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    a := 0
    a, (c:) = 1, 2
    a, (d:int) = 3, 4

    Remarque importante concernant l'affectation : Toutes les structures de données sont immuables. Lorsque nous mutons des index, nous créons une nouvelle copie à muter si quelque chose d'autre pointe vers la même structure de données. Ainsi, par exemple, après

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    x := [1, 2, 3];
    y := x;
    x[0] = 4

    y sera toujours [1, 2, 3]. Vous pouvez considérer x[0] = 4 comme une souplesse syntaxique pour x = [4] ++ x[1 :], bien que lorsque rien d'autre ne se réfère à la même liste, c'est en fait aussi rapide qu'une mutation.

    Par conséquent, l'appel d'une fonction sur une structure de données ne peut pas la muter. Il existe quelques mots-clés spéciaux qui mutent tout ce qui leur est donné. Il y a swap comme swap x, y pour échanger deux valeurs ; il y a pop et remove pour muter des séquences ; et l'instrument le plus rudimentaire de tous, consume vous donne la valeur après l'avoir remplacée par null là d'où elle vient. Après

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    x := [1, 2, 3, 4, 5];
    y := pop x;
    z := remove x[0]

    y sera 5, z sera 1, et x sera [2, 3, 4]. Il n'y a aucun moyen d'implémenter pop comme une fonction ; le mieux que vous puissiez faire est de prendre une liste et de retourner séparément le dernier élément et tout ce qui le précède.

    Vous pouvez implémenter vos propres « cellules de données mutables » facilement avec une fermeture :

    • make_cell := \init -> (x := init; [\ -> x, \y -> (x = y)])
    • get_a, set_a := make_cell(0)

    Structs

    Des types de produits super dénudés pour le moment. Pas de méthodes, d'espaces de noms ou autre. (Haskell a survécu sans eux pendant quelques décennies, nous

    • pouvons tergiverser.) Vous ne pouvez même pas donner aux champs des types ou des valeurs par défaut.
    • struct Foo (bar, baz);

    Vous pouvez alors construire une instance entièrement nulle Foo() ou toutes les valeurs avec Foo(a, b). bar et baz sont maintenant des fonctions d'accès aux membres, ou si vous avez un foo de type Foo, vous pouvez accéder, assigner ou modifier les champs comme foo[bar] et foo[baz]. bar et baz sont de nouvelles variables contenant des fonctions dans la portée dans laquelle vous avez déclaré cette structure, et peuvent être transmises en tant que fonctions à part entière, assignées à des variables, etc.

    Source : Noulith

    Et vous ?

    Que pensez-vous du langage Noulith ?

    Pensez-vous que le langage Noulith pourrait répondre aux critiques sur les langages les plus connus ?

    Voir aussi :

    La version 1.6.2 de Nim, le langage doté d'un transcompilateur vers C, C++ est disponible, elle corrige plus de 15 problèmes signalés et apporte quelques améliorations

    La version 3 de Scala, un langage orienté objet et fonctionnel, est disponible, elle apporte une nouvelle conception des abstractions contextuelles et améliore le système de types

    Go 1.18, le langage de programmation open source développé par Google, arrive avec la généricité par défaut, elle ouvrira de nouvelles solutions, d'approches et de paradigmes
    Contribuez au club : corrections, suggestions, critiques, ... Contactez le service news et Rédigez des actualités

  2. #2
    Membre du Club Avatar de vivid
    Profil pro
    Inscrit en
    février 2006
    Messages
    143
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : février 2006
    Messages : 143
    Points : 61
    Points
    61
    Par défaut
    Si tu maitrise le C... (ou autre) zéro intérêt, se casser le 'bol' a des vertus ...

Discussions similaires

  1. Réponses: 290
    Dernier message: 31/05/2013, 11h43
  2. Réponses: 130
    Dernier message: 04/02/2011, 11h11
  3. Choix d'un nouveau langage de programmation
    Par ProgVal dans le forum Langages de programmation
    Réponses: 9
    Dernier message: 09/01/2010, 16h20
  4. Comment rajouter un nouveau langage de programmation ?
    Par Acropole dans le forum Eclipse
    Réponses: 2
    Dernier message: 12/11/2009, 16h40
  5. Nouveau langage de programmation : le langage G
    Par G-FACTION dans le forum Autres langages
    Réponses: 10
    Dernier message: 19/07/2009, 20h58

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo