Microsoft présente Bosque, un nouveau langage fonctionnel
mar, 23/04/2019 - 10:40
La semaine dernière, Mark Marron, de Microsoft Research, a présenté Bosque, un nouveau langage de programmation, dans un court billet :
Le langage de programmation Bosque est conçu pour écrire du code simple, clair et facile à comprendre pour les humains et les machines. Les principales caractéristiques de conception du langage permettent d'éviter toute complexité accidentelle dans le processus de développement et de codage. L'objectif est d'améliorer la productivité des développeurs, d'améliorer la qualité des logiciels et de proposer une gamme de nouveaux compilateurs et de nouvelles expériences d'outils de développement.
Mark Marron présente par ailleurs Bosque dans un document technique de 18 pages qui nous apprend entre autres que ce langage dérive d'une combinaison de TypeScript, de ML, ainsi que de Node/JavaScript.
Le projet Bosque est sur GitHub. Bosque est un langage open source sous licence MIT. Les développeurs sont invités à s'impliquer dans le projet et/ou à faire leurs commentaires. La page GitHub détaille toutes les fonctionnalités du langage. Mais quelques paragraphes restent à écrire.
Le coup du langage clair et facile, on nous l'a déjà fait. Celui du langage sûr qui évite les erreurs également :-) Bosque apporte-t-il vraiment quelque chose de nouveau et de pertinent dans ces domaines ? C'est un peu la question.
Bosque est un langage fonctionnel pur. Cela signifie qu'il ne permet pas les affectations. Toutes les valeurs sont immuables, ce qui permet d'éviter les effets de bord, donc de nombreuses erreurs de programmation effectivement. Comme pour tous les langages fonctionnels, les fonctions sont des valeurs de premier ordre, ce qui signifie quelles peuvent être passées en arguments à d'autres fonctions, ou retournées par des fonctions.
Mark Marron souline que Bosque élimine la complexité des boucles des langages impératifs. Par exemple ce code JavaScript :
//Imperative Loop (JavaScript)
var: number[] a = [...];
var: number[] b = [];
/**
Pre: b.length == 0
**/
for(var i = 0; i < a.length; ++i) {
/**
Inv: b.length == i /\
forall i in [0, i) b[i] == a[i]*2
**/
b.push(a[i]*2);
}
/**
Post: b.length == a.length /\
forall i in [0, a.length) b[i] == a[i]*2
**/
Trouve son équivalent en Bosque :
//Functor (Bosque)
var a = List[Int]@{...};
/**
Pre: true
**/
var b = a.map[Int](fn(x) => x*2);
/**
Post: List[Int]::eq(fn(x, y) => y == x*2, a, b)
**/
Concrètement, pour nos lecteurs peu familiers avec la programmation fonctionnelle, une fonction lambda qui retourne le double de son argument est mappée sur une liste, c'est-à-dire appliquée sur chaque élément de la liste. Programmation fonctionnelle pure oblige, la liste de départ, ici a, n'est pas modifiée. L'opération retourne une nouvelle liste b en guise de résultat.
Ce nouveau langage apporte-t-il vraiment quelque chose ? De l'humble avis de votre serviteur, grand amateur de programmation fonctionnelle pure, pas grand chose. Est-ce que quelqu'un avait vraiment besoin d'un autre langage Clean, Mercury ou Haskell ? Rien n'est moins certain. La présentation de Mark Marron ne s'étend pas beaucoup sur deux pierres d'achoppement des langages fonctionnels purs incontournables dans les applications pratiques : les entrées/sorties et la programmation concurrente. Haskell, par exemple, résout le problème avec élégance au moyen des monades. Le moins que l'on puisse dire est que la présentation de Mark Marron ne s'étend pas sur le sujet.
La page GitHub du projet Bosque donne un programme de TicTacToe comme exemple concret complet. Dans le code, on voit un tableau de positions gagnantes déclaré comme ceci :
const winPositionOptions: List[[[Int, Int]]] = List[[[Int, Int]]]@{
List[[Int, Int]]@{ @[ 0, 0 ], @[ 0, 1 ], @[ 0, 2 ] },
List[[Int, Int]]@{ @[ 0, 1 ], @[ 1, 1 ], @[ 2, 1 ] },
List[[Int, Int]]@{ @[ 0, 2 ], @[ 1, 2 ], @[ 2, 2 ] },
List[[Int, Int]]@{ @[ 0, 0 ], @[ 1, 0 ], @[ 2, 0 ] },
List[[Int, Int]]@{ @[ 1, 0 ], @[ 1, 1 ], @[ 1, 2 ] },
List[[Int, Int]]@{ @[ 2, 0 ], @[ 2, 1 ], @[ 2, 2 ] },
List[[Int, Int]]@{ @[ 0, 0 ], @[ 1, 1 ], @[ 2, 2 ] },
List[[Int, Int]]@{ @[ 0, 2 ], @[ 1, 1 ], @[ 2, 0 ] }
};
Ce code est-il vraiment clair et facile à relire pour un humain ? La redondance de la déclaration des types nous parait au contraire assez lourde. Les listes et les tuples sont déclarés par @ {...} et @ [...] respectivement. En Haskell c'est [...] et (...) respectivement, ce qui n'est pas plus mal :-)
[/][/]