blog2geek.com
LLBAvatar de LLB

38 billets | Profil

Recherche Google

ce blog tous
Derniers billets Connexion
Archives

test

21/06/2007

Pourquoi F#, plutôt qu'OCaml ? (Partie 1)

Pourquoi F#, plutôt qu'OCaml ?
Et critique d'OCaml.

 

Avant propos : ce message met en valeur un certain nombre de défauts d'OCaml. Le but n'est pas de dire qu'OCaml est un mauvais langage ou de faire une critique objective et complète, il s'agit surtout d'expliquer pourquoi je lui préfère F#. Que les choses soient claires : je préfère largement OCaml à la plupart des langages considérés comme modernes.

La suite du billet se trouve sur cette page : Pourquoi F#, plutôt qu'OCaml ? (Partie 2).

 

Certaines personnes se rendent compte tardivement de l'intérêt de la programmation fonctionnelle. Il est toujours bon d'apprendre un langage fonctionnel, et même si notre boulot nous contraint d'utiliser autre chose (au hasard : C++, Java ou C#), comprendre la philosophie fonctionnelle est utile. Tous les langages récents possèdent en effet un héritage fonctionnel, plus ou moins prononcé. Dans l'enseignement, OCaml a souvent été mis en avant ces dernières années, si bien que beaucoup d'étudiants connaissent un peu ce langage. OCaml a beaucoup de qualités, mais ce n'est plus le langage que je conseillerais à quelqu'un qui veut programmer, qui veut faire quelque chose de concret. Je vais donc essayer de me justifier ici et de répondre à la question que plusieurs personnes m'ont posée : « Pourquoi utiliser F#, plutôt qu'OCaml ? »

 

Un environnement de développement

C'est triste à dire, mais OCaml ne possède aucun environnement de développement décent. Aucun. Il y a bien quelques éditeurs qui ont été écrits, mais dans l'ensemble, ils ne valent pas grand-chose et ne vont pas beaucoup plus loin que la coloration syntaxique. Il y a bien Emacs, qui est souvent conseillé, mais c'est loin d'être optimal. Je ne dis pas du mal d'Emacs, mais de son mode pour Caml : il n'est même pas fourni de base dans Emacs, et il ne fournit que le minimum. Il est agréable pour utiliser le mode interactif, mais ça ne rivalise pas avec un véritable environnement dédié.

De son côté, F# est fourni avec une extension de Visual Studio. Complétion de code, affichage des fonctions disponibles avec leur description (plutôt que de fouiller dans un fichier .mli caché), vérification du code au moment de la frappe (oui, vérification syntaxique et de typage), affichage du type des variables (très utile, puisqu'ils sont inférés), etc. Mais bien entendu, ceux qui ont des critiques à faire vis-à-vis de Visual Studio pourront toujours utiliser les éditeurs prévus pour OCaml.

 

Windows

Dommage aussi, même si OCaml est parfaitement portable, il n'est pas agréable de travailler avec sous Windows. À tel point que beaucoup de personnes, dans les communautés de Caml, conseillent de passer sous un Unix. Changer de système d'exploitation, juste pour utiliser un langage. En plus du problème des éditeurs, la majorité des bibliothèques pour Caml sont conçues pour les utilisateurs d'Unix. Même GODI, ce système de paquets pour simplifier l'installation de bibliothèques ne tourne *que* sous Unix. Ce qui nous amène au troisième point. F#, lui, est conçu sous Windows et fonctionne parfaitement sous ce système. Mais il est aussi testé régulièrement sous Linux et sous Mac. J'ai récemment testé un compilateur (que j'ai écrit en F#) sous Linux, et ça a fonctionné directement, sans nécessiter le moindre changement. Le code généré est lui-même valable, grâce à Mono.

 

Les bibliothèques

Force est constatée qu'il y a peu de bibliothèques pour OCaml. Dans la distribution standard, il y a juste le minimum. Non, même pas le minimum diront certains : il n'y a pas de fonction de haut-niveau pour faire du réseau. La manipulation des expressions rationnelles n'est pas vraiment agréable (il est souvent conseillé d'utiliser une bibliothèque annexe) et la bibliothèque de chaines de caractères est risible : il y a tout juste une vingtaine de fonctions. Bien sûr, des gens ont créé des bibliothèques, pour essayer de pallier ces manques. Voici par exemple la liste des fonctions ajoutées dans la "extlib", juste pour la manipulation de strings : init, find, split, nsplit, join, slice, lchop, rchop, of_int, of_float, of_char, to_int, to_float, ends_with, starts_with, enum, of_enum, map, fold_left, fold_right, explode, implode, strip, exists, replace_chars, replace.

Oui, ça fait beaucoup de choses qui auraient dû être là de base. Pour les besoins les plus courants, on peut donc trouver une solution, en cherchant sur Internet. Mais gare à vous si vous avez des besoins plus spécifiques. Par exemple, écrire un jeu en Caml serait assez périlleux (il parait que le support d'OpenGL notamment laisse à désirer). Ou alors, vous n'avez plus qu'à écrire les bindings vous-même.

De son côté, F# a accès à une large bibliothèque (celle de .NET). Cette bibliothèque devrait répondre aux besoins courants, sans avoir à installer quoi que ce soit d'autre. Par exemple, on peut écrire une application graphique en 3 lignes. Si jamais les fonctions de base ne suffisent pas, on peut trouver facilement ce qu'il faut sur le net. Par exemple, un moteur 3D, un moteur physique et tout ce qu'il faut pour créer un vrai jeu.

 

Évolution

OCaml semble évoluer lentement. Les concepteurs ne semblent pas avoir envie de populariser le langage (en dehors de la recherche traditionnelle). Exemple marquant : la extlib a été commencée en 2003 et rien n'a changé depuis. Ils n'ont même pas pris la peine d'intégrer cette bibliothèque, pourtant basique, dans la distribution officielle.

De même, la générateur de parsers Menhir, écrit par des personnes l'INRIA, et destiné à remplacer OCamlyacc n'est toujours pas dans la distribution de base. Pourtant, il est conseillé par tout le monde et surpasse de loin OCamlyacc. Ce qui est triste aussi, c'est que Menhir est distribué avec ses sources, et qu'aucun binaire Windows n'est fourni : il y a de nombreuses dépendances, et je ne sais pas si quelqu'un l'a déjà compilé en natif sous Windows.

F# évolue très vite. D'importantes fonctionnalités sont ajoutées régulièrement. Les feedbacks des utilisateurs sont pris en compte, il est possible de discuter des choix techniques avec l'équipe de Microsoft. Les sources étant disponibles, il est même possible d'envoyer des patches ou d'implémenter la fonctionnalité de ses rêves (je l'ai fait il y a quelques jours, ça a été très bien vu par l'équipe de F#, et ça pourrait être intégré pour la prochaine publication).

 

La surcharge

C'est amusant de voir le nombre de développeurs Caml qui pensent que la surcharge n'est pas utile ou est dangereuse. Je trouve ça mignon et naïf, un peu comme quand un développeur Java essaie d'expliquer que la surcharge d'opérateurs n'apporte rien, ou quand un développeur C++ croit qu'un garbage collector est une mauvaise chose. Pour ceux qui sont vraiment sceptiques, comparez les deux versions suivantes du même code.

OCaml :
let x = Int64.add 38L 4L
let f y = Int64.div (Int64.mul x (Int64.of_int y)) 10L

F#:
let x = 38L + 4L
let f y = x * (int64 y) /10L

Voilà. C'est ce qui arrive aux imprudents qui veulent utiliser autre chose qu'un int (sur 31 bits) en Caml. Comptez donc le nombre de fois que le terme "Int64" apparait. Quatre fois, en deux lignes. Quelqu'un vous a dit que Caml faisait de l'inférence de types ? Non, vous avez dû rêver. Et sinon, vous voulez utiliser un float sur 32 bits en Caml ? Ou un entier sur 8 bits ? Non, vous ne le voulez pas bien sûr. Ce n'est pas possible.

L'exemple ci-dessus ne vous a toujours pas convaincu, car vous n'utilisez pas d'int64 ? Dans ce cas, regardez un peu le nom des fonctions suivantes : abs, abs_float, Big_int.abs_big_int, Num.abs_num, Int64.abs, Nativeint.abs. Comment ? Vous en avez marre d'écrire le type partout, et vous voulez vraiment de l'inférence de type ? Hé bien, utilisez F#.

Regardez aussi ces fonctions-là : print_string, print_char, print_int, print_float. Oui, encore le même problème, mais il est encore plus marqué : comment afficher l'AST que vous venez de définir ? Ou votre liste de listes d'entiers ? Ou votre dernière structure ? Ou un tuple ? Je crois que vous êtes bons pour écrire votre propre print_foo. Ou pour utiliser F#.

En F#, vous pouvez afficher n'importe quelle valeur, de n'importe quel type. Il suffit d'appeler la fonction print_any (ou output_any en précisant le canal de sortie). Ou encore, d'utiliser le symbole %A dans votre printf. L'affichage générique ne vous convient pas ? Ce n'est pas grave, il est possible de le redéfinir et de faire du pretty-printing avec les fonctions de StructuredFormat.

 

Toujours pas convaincu ?

Comme je l'avais déjà écrit dans un autre billet, vous gagnez en prime : de l'introspection, les compréhensions de listes, un syntaxe plus légère et bien plus élégante, du pattern-matching extensible (j'y reviendrai)... Mais aussi, grâce à .NET, vous pourrez utiliser F# dans vos pages web (avec ASP.NET), pour remplacer le flash (Silverlight), en remplacement ou en complément d'un autre langage .NET, etc. À vrai dire, si migrer vers Caml est lourd, couteux et dangereux pour une entreprise, migrer de C# vers F# ne présente quasiment aucune difficulté.

J'ai converti plusieurs fois du code C# en F# ; la plupart du temps, cela s'est limité à : supprimer les points-virgules de fin de ligne, enlever les informations de types, virer les accolades et virer les parenthèses superflues. C'est tout. Le gain par rapport à C# est assez important : inférence de type, sûreté, pattern-matching, code plus court (de l'ordre de 40%), fonctionnel, etc.

 

Alors, décidé ?

 

Si non, la suite du billet se trouve sur cette page : Pourquoi F#, plutôt qu'OCaml ? (Partie 2).

> Rédiger un commentaire

19:03 21/06/2007 - inconnu

Heh, moi je veux bien essayer, y'a qu'a convaincre mon boss :)
--
Rubix

21:09 26/06/2007 - inconnu

Vraiment pas désolé... mais ta présentation ne peut pas convaincre, elle ne pourrait que persuader. Par exemple, le utilisateurs de solutions microsoft ont de grandes chances d'être persuadés.
Par contre il y a une chose de vraie et qui rend triste dans ce que tu dis, personne ne se bouge pour ocaml, et c'est peut-être ce qui le perdra... je ne l'espère pas.
Merci pour ta présentation en tous cas. Peut-être un peu plus de cas concrets la prochaine fois ;) 

23:23 13/08/2007 - inconnu

Mais, heu... comment c'est atterri sur prg.reddit?! Non que ce soit foncièrement inintéressant, mais là ça sort un peu du lot.

19:17 18/08/2007 - LLB

Aucune idée, ce n'est pas moi qui l'ai ajouté.
--
LLB.

> Rédiger un commentaire