Posté par kantien .
En réponse au journal L'increvable.
Évalué à 2.
Dernière modification le 25 mars 2016 à 17:07.
Il est remarquable d'arriver à taper autant de mots compliqués sans quitter des yeux son propre nombril !
Ce n'est pas de lui dont il parlait dans le commentaire juste en-dessous ? Comme il se met à jouer au philosophe, j'ai cru qu'il s'était remémorer l'injonction socratique : « Connais-toi toi même ! ». Telle était l'inscription sur le temple de Delphes, temple dont l'oracle (la pythie) aurait répondu à Chéréphon qu'il n'y avait pas d'homme plus sage que Socrate dans la cité athénienne. S'interrogeant sur le sens d'une telle parole, ce dernier serait arrivé à cette conclusion : « tout ce que je sais, c'est que je ne sais rien ». Entendre par là, non qu'il était ignorant, mais contrairement à tous les sophistes qui se prétendaient les détenteurs de la sagesse, et par leur rhétorique trompaient le peuple d'Athènes, lui, Socrate, ne prétendait pas savoir ce qu'il ignorait, et que sa sagesse consistait en une quête perpétuelle vers la Vérité et le Bien — qu'il ne prétendait pas posséder. Du moins, tel est le Socrate que nous a décrit Platon.
À moins que notre seigneur du temps, le Doc. who — lui qui a vu tant de choses qu'aucun humain ne peut imaginer — pousse l'analogie socratique jusqu'à considérer que, tel le peuple athénien et la démocratie athénienne, le peuple linuxfrien le condamne à mort, sous la forme de moinsage répété, parce qu'il remettrait trop en cause, publiquement, la doxa admise dans nos rangs. Néanmoins, Socrate ne s'était jamais abaissé à insulter ses interlocuteurs. De plus, en ce jour de vendredi Saint, Jésus le Maître de L'Évangile — dont la doctrine fût qualifiée par Nietzsche de « platonisme pour la plèbe » — subit le même sort que Socrate. Et face à ses disciples qui se désolaient de le voir ainsi traiter et agoniser sur la croix, il leur dit : « Pardonnez leur, ils ne savent pas ce qu'ils font. » On est, là encore, bien loin de l'arrogance, de la suffisance, de l'insulte et bien plus proche de la sagesse.
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
Ah la mathésis universalis ou la caractéristique universelle de Leibniz ! Elle en a fait couler de l'encre :
Deux mots seulement sur l’art de combiner les signes ; ce que je vais en dire, sans être d’une bien grande importance, n’est pas précisément à dédaigner. Les termes dont je me sers pour expliquer ces principes présentent, par leur extrême simplicité, une analogie frappante avec les signes. Leibniz vantait fort une caractéristique dont il était l’inventeur ; tous les savants ont regretté qu’elle fût ensevelie avec ce grand homme. Ce regret m’est une occasion de dire mon sentiment sur l’art combinatoire. J’avoue que dans ces paroles du grand philosophe, je crois apercevoir le testament du père de famille dont parle Esope : étant sur le point d’expirer, il déclara en secret à ses enfants qu’il avait un trésor caché quelque part dans son champ, mais, surpris par la mort, il ne put leur indiquer l’endroit où il l’avait enfoui ; ce fut pour les enfants l’occasion de fouiller leur champ avec la plus grande ardeur, de le creuser et de le retourner en tous sens ; tant et si bien que, quoi que trompés dans leurs espérances, ils finirent par se trouver plus riches de la plus grande fécondité de leur champ. Nul doute que ce ne soit là le seul fruit à retirer de la recherche de ce mécanisme inventé par Leibniz, si l’on doit s’en occuper encore.
Elle fût effectivement remise au goût du jour par Frege et son idéographie, suivi par Russell. Néanmoins, je considère que les résultats d'incomplétude de Gödel (ou son équivalent informatique : le problème de l'arrêt) ont mis un terme définitif à la quête d'une telle langue. Comme le disait Wittgenstein : « ce que le langage signifie, cela ne se dit pas, cela se montre ». Mais, les enfants et héritiers qui ont creusé et retourné dans tous les sens ce sont effectivement retrouvés plus riches de la fécondité de leur champ : ce n'est point ici que l'on soutiendra le contraire. ;-)
Et puis ces recherches ont grandement inspiré le -calcul, et donc tous les langages avec paradigme fonctionnel : Lisp, Scheme, Clojure, Haskell, OCaml… et quoi que de mieux que ce paradigme pour incarner la théorie kantienne du schématisme (cf. Critique de la Raison Pure) et comprendre ce qu'un kantien entend derrière le concept de schème. \o/
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
Posté par kantien .
En réponse au journal L'increvable.
Évalué à 3.
Dernière modification le 23 mars 2016 à 11:57.
Le problème n’est pas seulement l’entreprise, mais il faut avancer 100€ d’un coup… pour des gens qui gagne difficilement leur vie, il est plus facile de sortir 8€/mois que 100€ une fois dans l’année.
Tout à fait, et c'est une des raisons pour lesquelles même si l'offre apparaissait sur le marché elle ne satisferait pas nécessairement la demande.
Je voulais juste souligner que l'objection de reynum n'était rien d'autre qu'un non sequitur, et qu'il n'est pas difficile d'expliquer la nature des offres disponibles autrement que par l'existence d'un complot généralisé sur l'obsolescence programmée (avec un cartel en arrière plan pour justifier la non apparition d'un concurrent) : le principe que tu invoques, reposant sur une contrainte du consommateur, pouvant servir à cela.
Finalement, tant les producteurs que les consommateurs ne sont pas des idiots et ne limitent pas leurs calculs et raisonnements économiques au seul bilan comptable.
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
Et encore, dans le commentaire ci-dessus, je n'ai pas pris en compte le volume des ventes. L'entreprise pourrait toujours baisser sa marge par collant (à l'unité), mais accroître son bénéfice total par hausse du volume des ventes (si l'offre était réellement présente, elle écraserait la concurrence et augmenterait considérablement son volume de vente).
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
D'autant que dans l'exemple hypothétique étudié dans l'article, après étude de marché l'entreprise qui fabrique les collants a constaté que les clientes potentielles sont prêtes à débourser 104€ par an pour leurs collants. Alors entre 52€ et 104€, il y a encore de la marge, elle pourrait augmenter encore un peu pour amortir le coût des éventuelles garanties et rester toujours nettement moins chers que la concurrence qui est à 104€. Non décidément, si un tel concurrent n'apparaît pas sur le marché c'est :
soit il y a un cartel des fabricants de collants
soit l'offre ne satisfait pas la demande (hypothèse retenue dans l'article)
Pour moi, le commentaire auquel tu réponds est écrit par une personne, certainement pas décérébrée, mais qui ne comprend pas grand chose à l'économie.
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
Je n'ai pas testé encore flambda, mais sauf surprise il inline juste la fonction, mais sans changer la sémantique d'évaluation, ce qui veut dire que les arguments sont évalués avant. Par exemple : let () = iff true (print_int 4) (print_int 2) va afficher 42.
Effectivement j'ai parlé trop vite, flambda fait de même pour ne pas changer la sémantique d'évaluation, même si les deux compilateurs (le classique et le flambda) comprennent que l'expression finira dans la première branche. Ils inlinent et suppriment même le test, mais évaluent quand même les expressions à cause des effets de bord qu'elles contiennent. En revanche en l'absence d'effet de bord, c'est compilé comme pour les macros en Common Lisp.
Après que les macros offrent toutes les possibilités que tu décris, je ne le nie pas : cela permet de gérer deux stratégies différentes de beta-réduction sur les -termes. À l'exécution en commençant par les paramètres sur les fonctions, ou à la compilation sur le corps de la macro. Là où pour l'instant OCaml ne dispose que de la première stratégie, même si l'inlining a fortement à voir avec la seconde. Ce sont deux approches du -calcul qu'il est intéressant de comparer, même si je ne lâcherai pour rien au monde la puissance du système de types d'OCaml (statique et très grande expressivité). Le système de -calcul typé le plus puissant étant Coq comme je l'avais expliqué ici : un programme Coq qui compile est garanti sans bug, comme le compilateur CompCert (le seul à ma connaissance) développé par Xavier Leroy, le BDFL OCaml.
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
Par contre la macro est évaluée au moment de la compilation, donc une seule fois.
Il reste juste à noter que cette macro est assez simple mais qu'elle pourrait faire des calculs complexes, parcourir les expressions qu'on lui passe en paramètre (il s'agit de simples listes), faire n'importe quoi pour générer le code Lisp destiné à la remplacer. Il s'agit simplement de code Lisp quelconque manipulant des listes (parcours, construction, …).
Est-ce que c'est plus clair ?
Oui c'est plus clair, je n'avais pas fait attention à ta remarque qui expliquait que les macros étaient exécutées à la compilation (ce qui explique leur dénomination).
En fait le compilateur OCaml fait la même chose avec certaines fonctions, et dans la nouvelle version à venir il le généralise via une nouvelle représentation intermédiaire, qui ne sera qu'optionnelle pour cette version, mais sera sans aucun doute la base pour les versions ultérieures. Par exemple le compilateur actuel remplace systématiquement les appels à ma fonction iff par if b then e1 else e2 (comme si c'était une macro en Common Lisp), mais le nouveau système pousse l'idée plus loin en l'étendant aux fonctions récursives et en « exécutant » au maximum le code de la fonction qu'il développe. Tu pourras en lire plus sur la partie que j'ai consacré, avec chicco, au système FLambda dans la dépêche en cours de rédaction.
Sinon if est aussi une primitive en OCaml, comme en Common Lisp, mais n'est en fait qu'un cas particulier d'une autre structure primitive le pattern matching qui est une version généralisée de ta macro cond : if b then e1 else e2 n'est qu'un alias pour match b with true -> e1 | false -> e2, et on peut mettre autant de cas que l'on veut dans l'analyse et pas seulement en faisant des tests sur les booléens mais sur la forme et la structure du type que l'on étudie. Cela parce que, comme pour Common Lisp, toutes les valeurs sont essentiellement des références (sauf les types int, bool, char et les constructeurs constants comme la liste vide) et accessible uniquement via leur constructeur de type.
Par exemple pour définir la fonction list_map qui applique une fonction à tous les éléments d'une liste, on l'écrira
(* en OCaml le type des listes se définit comme *)type'alist=|Nil(* la liste vide *)|Consof'a*'alist(* le nom du constructeur est issu du nom de l'opérateur en Lisp ;-) *)(* [] est un alias pour la liste vide et hd :: tl un alias pour Cons(hd, tl) la liste [1; 2; 3] se construit par Cons(1, Cons(2, Cons(3, Nil))) et on retrouve la structure de liste imbriquée à la Lisp *)letreclist_mapfl=matchlwith(* soit la liste est vide et on renvoie la liste vide *)|[]->[](* soit elle a une tête et une queue, alors on applique f à la tête et list_map à la queue *)|hd::tl->(fhd)::(list_mapftl);;(* on peut alors faire une fonction qui renvoie la liste des successeurs d'une liste d'entiers *)letsucc_listl=list_map(funn->n+1)l;;(* mais à la compilation il va développer list_map comme une macro et simplifier le tout en *)letsucc_listl=letreclist_map'l=matchlwith|[]->[]|hd::tl->(hd+1)::(list_map'tl)inlist_map'l;;
Sinon pour la coloration de code en Common Lisp, je mets lisp comme langage.
D'accord, si je comprends bien ce qui distingue une fonction d'une macro c'est le mode d'évalution des paramètres : pour une fonction ils sont passés par valeur, là où pour une macro ils sont passés par nom (dans ce cas l'évaluation est-elle paresseuse, i.e évalué une seule fois à la première utilisation du terme, ou recalculer à chaque usage du terme ?).
Par curiosité, dans ton exemple en OCaml tu écris ça :
(* je code le test if-then-else en fonctionnel pure *)letiffbe1e2=ifbthene1elsee2
Dans un langage comme Java ça ne marche pas parce que les expressions e1 et e2 seraient évaluées systématiquement avant d'être passées en paramètre à la fonction iff.
En Common Lisp ça marche si iff est une macro, ce qui permet de ne pas évaluer systématiquement les deux expressions avant de choisir le résultat à renvoyer.
En OCaml ça marche parce que le langage est purement fonctionnel et que le compilateur va se débrouiller pour n'évaluer que les expressions nécessaires ? Ou tu as fait un exemple simplifié ?
Comme l'a dit anaseto, en OCaml les paramètres sont passés par valeur, ils sont évalués par l'appelant avant d'être passés à la fonction appelée (à la manière des fonctions Lisp et non des macros). La seule exception concerne les opérateurs sur les booléens : && (et) et || (ou) qui sont évalués de gauche à droite et de façon paresseuse. Cela étant en Comme Lisp if est une macro ou une fonction ?
Comme l'a aussi précisé anaseto, il est possible de faire de l'évaluation paresseuse en OCaml via le module Lazy. Le même exemple (factoriel) avec iff en mode macro :
letle=(<=)andmul=(*)andminus=(-);;valle:'a->'a->bool=<fun>valmul:int->int->int=<fun>valminus:int->int->int=<fun>(* maintenant iff n'évalue que e1 ou que e2 suivant la valeur du booléen *)letiffbe1e2=ifbthenLazy.forcee1elseLazy.forcee2valiff:bool->'alazy_t->'alazy_t->'a=<fun>letrecfactorial?(acc=1)n=(iff(len1)(lazyacc)(lazy(factorial~acc:(mulaccn)(minusn1))))(* on pourrait utiliser (pred n) au lieu de (minus n 1) *)valfactorial:?acc:int->int->int=<fun>factorial5;;-:int=120
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
Posté par kantien .
En réponse au journal C++17 est sur les rails.
Évalué à 3.
Dernière modification le 18 mars 2016 à 17:34.
Effectivement je ne connaissais pas la terminologie Lisp, une macro n'est rien d'autre qu'une fonction si je comprend bien ? ou sont-ce des fonctions d'une forme particulière ? De fait la syntaxe Lisp représente directement son AST, là où en OCaml on passe par des modules du compilateur pour le manipuler. Mais il me semble que c'est essentiellement pour des raisons de typage : le Lisp est du lambda-calcul faiblement typé, là où OCaml est du lambda-calcul fortement typé statiquement.
Après le lambda-calcul est certes un outil essentiellement théorique (utile pour la théorie des langages), mais c'est juste du Lisp encore plus fruste : il n'y a qu'un seul opérateur, à savoir lambda, et on ne peut pas donner de nom aux termes (il n'y a pas d'opérateur d'affectation comme defun ou let). Par exemple ((lambda x) (x)) est la fonction identité ou encore ((lambda x) (y)) est la fonction constante égale à y. Ainsi si on applique le premier terme à n'importe quoi (n'importe quelle s-expression dont le seul opérateur de construction est lambda) alors il le renvoie, du genre (((lambda x) (x))((lambda z) (u v))) s'évalue en ((lambda z) (u v)).
Sinon, on peut aussi coder du OCaml à la manière de Lisp en notation purement préfixée. Il suffit d'entourer un opérateur infixe par des parenthèses pour l'utiliser en préfixe comme dans ( + ) 1 2 qui vaut 3.
Exemple sur la fonction factorielle en récursif terminal :
(* je commence par renommer les opérateurs infixes sous forme préfixe *)letle=(<=)andmul=(*)andminus=(-)(* je code le test if-then-else en fonctionnel pure *)letiffbe1e2=ifbthene1elsee2(* maintenant je code à la Lisp *)letrecfactorial?(acc=1)n=(* pour des raisons de typage on rajoute le mot clé rec et le paramètre optionnel est en premier *)(iff(len1)acc(factorial~acc:(mulaccn)(minusn1)))(* en OCaml plus idomiatique cela donnerait *)letfactorialn=letrecloopaccn=matchnwith|1->acc|_->loop(acc*n)(n-1)inloop1n
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
Posté par kantien .
En réponse au journal C++17 est sur les rails.
Évalué à 3.
Dernière modification le 18 mars 2016 à 11:34.
Un des intérêts des macros est de permettre d'étendre la syntaxe du langage, je ne vois pas en quoi c'est un problème de conception. S'il n'y a pas de mécanisme d'extension tu peux moins écrire les choses comme tu veux. Et dans le code d'Eliom (c'est peut-être là que je n'ai pas tout compris) j'ai l'impression que des outils de compilation intégrés au langage sont utilisés. Donc pas de macros mais on utilise des outils propres aux compilateurs pour étendre la syntaxe…
Tu as bien compris, et l'intérêt de passer par des outils propres aux compilateurs pour étendre la syntaxe plutôt que d'utiliser des macros c'est :
uniformiser et simplifier l'écriture d'extension
conserver les gardes-fou du typage statique
Jusqu'à il y a deux ans, pour étendre la syntaxe OCaml on utilisait un pré-processeur camlp4 (ce qui, au fond, est similaire à de la macro) mais c'était chiant à écrire et on se retrouvait avec des tonnes de syntaxes différentes entre les projets : la coopération entre projet était rendue plus compliqué. Avec la nouvelle façon de faire, via ppx, cela se passe au niveau de la manipulation des AST et les extensions sont uniformisées : la coopération est simplifiée et s'est accrue. Par exemple dans le cas de Eliom :
letfx=x+1(* définition usuelle d'une fonction en ocaml, ici le successeur *)let%clientfx=x+1(* extension de syntaxe pour dire que cette fonction est définie côté client *)let%serverfx=x+1(* la même mais définie côté serveur *)let%sharedfx=x+1(* elle est accessible aussi bien côté serveur que côté client *)
Étendre la syntaxe d'un langage est une chose fort utile, mais il ne faut pas que cela défigure complètement la syntaxe initiale (ce qui est tentant avec les macros) et quitte à générer du code par modification de la syntaxe autant le faire au niveau de l'AST : ce que montre la signature du foncteur que tu cites (une signature en OCaml c'est l'équivalent des headers en C ou C++, et un foncteur est proche des templates du C++ : une fonction dont les paramètres sont des modules, i.e. des structures ayant une signature donnée).
Les foncteurs (comme les templates en C++) est aussi une manière beaucoup plus simple et sécurisée (meilleur contrôle du typage) de générer du code. Un exemple simple, en OCaml, et la cas de la structure d'ensemble : pour construire des ensembles sur un type de donné quelconque, il suffit de le munir d'une relation d'ordre et d'utiliser le foncteur Set.Make
(* on définit une structure d'ordre sur les entiers *)moduleIntOrd=structtypet=intletcompare=Pervasives.compare(* c'est une fonction d'ordre générique sur n'importe quel type *)end(* on la passe en arguments au foncteur Set.Make *)moduleIntSet=Set.Make(IntOrd)(* et cela génère automatiquement toutes ces fonctions *)moduleIntSet:sigtypeelt=inttypet=Set.Make(IntOrd).tvalempty:tvalis_empty:t->boolvalmem:elt->t->boolvaladd:elt->t->tvalsingleton:elt->tvalremove:elt->t->tvalunion:t->t->tvalinter:t->t->tvaldiff:t->t->tvalcompare:t->t->eltvalequal:t->t->boolvalsubset:t->t->boolvaliter:(elt->unit)->t->unitvalfold:(elt->'a->'a)->t->'a->'avalfor_all:(elt->bool)->t->boolvalexists:(elt->bool)->t->boolvalfilter:(elt->bool)->t->tvalpartition:(elt->bool)->t->t*tvalcardinal:t->eltvalelements:t->eltlistvalmin_elt:t->eltvalmax_elt:t->eltvalchoose:t->eltvalsplit:elt->t->t*bool*tvalfind:elt->t->eltvalof_list:eltlist->tend(* que je peux utiliser dans la foulée *)lete=IntSet.empty(* e est l'ensemble vide *)lete=IntSet.add1e(* je lui ajoute l'élément 1 *)(* je teste si 1 est élément de l'ensemble *)InSet.mem1e-:bool=true
Pour ce qui est du parenthésage, c'est une question de goût, mais la syntaxe de Lisp qui colle à la syntaxe du lambda-calcul n'est pas toujours des plus simples à lire. Par exemple la fonction qui consiste à échanger l'ordre d'application des arguments d'une fonction s'écrit en -calcul : z.( x.( y.(z y)x)), là où je trouve la syntaxe let swap z x y = z y x plus « parlante » et moins « lourde ».
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
Pour juste un petit exemple : écrire un générateur html qui permet de mêler du code Lisp et du code html (comme les jsp de java mais avec tout le langage Lisp sous la main, sans un (en fait deux dans le cas des jsp, sans compter les balises personnalisées) langages supplémentaires à apprendre) ça nécessite même pas 100 lignes de code, avec les échappements html appliqués automatiquement. Et si tu écris des applications web tu sais à quel point la sécurité de la génération des pages est difficile (sinon je te le dis ;) : ajouter du texte dans des pages dont les méta-données sont du texte c'est assez délicat parce qu'il faut faire attention partout et que par définition les humains ne sont pas très doués dans ce domaine). Étendre ce générateur pour qu'il traite tous les cas (échappement des paramètres javascript, échappement correct des url, jetons dans les urls, …) c'est quelques centaines de lignes de code. Avec une syntaxe finale qui mêle harmonieusement lisp et html (ou ce qui le représente), sans avoir rien d'autre à apprendre, y compris pour créer tes propres composants de présentation (de simples fonctions/macros Lisp). C'est un exemple où il y a peu de choses à apprendre pour savoir comment ça marche, qui libère le développeur de pas mal de problèmes (moins de choses à penser partout) et qui permet à des gens ayant une expérience modérée du développement web d'éviter les conneries. À l'échelle d'un site de 3 pages ce n'est pas intéressant mais si tu réalises des applications plus complexes c'est vite rentabilisé.
Cela ressemble à ocsigen ce que tu décris, en moins développé. C'est écrit en OCaml (c'est la même famille que Lisp : -calcul avec très impératif, et aussi objet, mais en mieux typé et sans les horreurs du paranthésage et des macros — pour moi, avoir besoin de macros est un défaut de conception dans un langage) et ça génère du html garanti conforme (grâce au système de types du langage) ainsi que de la compilation OCaml vers javascript : ce qui permet d'écrire une webapp en full-ocaml en codant les parties client et serveur dans le même langage, tout en bénéficiant de la puissance et de la sécurité de son système de types.
En exemple, tu as l'application graffiti : proof of concept d'une application collaborative de dessin (si tu ouvres deux navigateurs sur la page, ce que tu dessines dans l'un est répercuté sur le caneva de l'autre) dont le code fait 200 lignes.
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
On a toujours le choix, mais on a pas toujours la paire de couilles qui va avec.
Le courage est-il un attribut qui n'est caractéristique que des personnes possédant une paire de couilles ? Le courage serait-il un attribut exclusivement masculin ? La phrase aurait eu le même sens, et la même portée en la formulant : « On a toujours le choix, mais on n'a pas toujours le courage qui va avec ! » (j'y ai simplement substitué ton expression, quelque peu phallocrate, par un point d'exclamation — je suppose qu'elle avait pour but de souligner la détermination inébranlable que nécessite le courage).
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
Tu sais aussi que c'est le même genre d'erreur si il y a redefinition de type, ce qui donne :
Error: This expression has type mytype_t but an expression was expected of type mytypet_
Je crois qu'ils sont en train de travailler dessus, ce qui manque c'est les adresses dans les fichiers du pourquoi de l'erreur, en gros, les 2 définitions qui entre en conflit.
Effectivement, à ce niveau tu as raison. Il me semble aussi qu'ils travaillent dessus, ce qui est d'ailleurs plus une question de temps à consacrer au sujet que de difficultés. À mon avis, si ce n'est pas encore présent c'est que ceux qui s'occupent du compilateur bossent tous sur Emacs et que leurs extensions résolvent déjà ce problème, donc de leur seul point de vue il n'existait pas.
Pour des pures débutant, je ne suis pas sur que map et fold_left fasse si peur. Gérer correctement une boucle peut être bien plus compliqué que l'on peut le croire (erreur d'off by one). Et une fois que l'on a gouter au filtrage de type, on a plus besoin du "if" :)
Le if peut bien servir de temps en temps (test d'égalité physique ou structurelle) mais assurément le pattern matching est le cœur d'un code OCaml. Mais l'ouvrage que je citais amène bien évidemment tous ces concepts (pour preuve l'exemple de code que j'ai cité) mais dans une approche progressive que je trouve bien faite sur le plan pédagogique. Et l'on n'y trouve pas tous les gros mots que tu as cités : monades, type algébrique, clôture, currification… ou du moins pas d'entrée de jeu. Il n'y est jamais question de monade (c'est indispensable en Haskell pour les IO, mais pas en OCaml) ni de clôture (il me semble), et ils parlent un peu de types algébriques et de currification (c'est indispensable) mais sans rentrer dans le détail : c'est inutile, il vaut mieux apprendre par l'exemple. Mais l'on aborde des techniques évoluées du langage comme la fonctorisation.
Pour revenir sur la non-nécessité des monades en OCaml, qui reste pour moi le concept le plus abstrait et sans doute le plus dur à comprendre dans ta liste, je vais revenir sur le code que j'avais cité en exemple. Au fond ce qu'ils codent pour avoir des tableaux persistants c'est un système de contrôle de version sur des tableaux : faire un set c'est faire un commit sur la structure et la fonction reroot a pour rôle de se rebaser sur le tableau sur lequel on veut opérer : on modifie le graphe des diff jusqu'à ce que notre tableau soit à la base et un « véritable » tableau. Et pour faire cela, ils manipulent des pointeurs ce qui est impossible en fonctionnel pur à la Haskell. Néanmoins pour l'utilisateur d'une telle structure de données, on lui présentera cette interface dans le fichier .mli :
La fonction reroot fait partie de la machinerie interne (du point de vue du mathématicien, c'est un lemme qui n'a pas besoin d'être connu de l'utilisateur), la représentation concrète du type lui est cachée (il ne peut donc pas manipuler les pointeurs) et pour lui tout ce passe comme si c'était du fonctionnel. C'est pour cela que les auteurs aiment bien définir ainsi une des caractéristiques du paradigme fonctionnel :
Une structure de données persistantes n'est pas nécessairement codée sans effet de bord. La bonne définition de persistant est observationnellement immuable et non purement applicatif (au sens de l'absence d'effet de bord). On a seulement l'implication dans un sens : purement applicatif ⇒ persistant. La réciproque est fausse, à savoir qu'il existe des structures de données persistantes faisant usages d'effets de bord.
Et effectivement la structure des tableaux persistants fonctionne avec des effets de bord (les fonctions set et reroot) mais cela c'est en interne et l'utilisateur ne l'observe pas : pour lui la structure est persistante.
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
J'avais espoir dans oscigen, mais je ne comprends rien à leur super tuto. De plus, il n'utilise pas du ocaml standard.
Si c'est juste pour avoir un serveur web, il y a ocsigen server. Après les tutos sont surtout là si tu veux faire une webapp en full-OCaml avec le framework eliom qui permet de coder les parties clients et serveurs en même temps. Et 200 lignes de code pour faire une appli simple de dessin collaboratif, c'est pas mal je trouve.
Qu'entends-tu par « il n'utilise pas du OCaml standard » ? Est-ce l'usage de fichier .eliom ? Cela est du à la nécessité de compiler différemment les code clients et serveurs que l'on met dans le fichier entre les balises [%%client], [%%server] ou [%%shared], mais entre ces balises c'est bien du OCaml standard.
Sinon il y a aussi cohttp développé par l'équipe de mirage.
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
Honnêtement je trouve que c'est un reproche aussi fréquent qu'immérité.
Je suis bien d'accord avec toi, mais je l'ai souvent entendu c'est pour cela que je l'ai précisé. Et effectivement, elle est bien plus fournie que la bibliothèque standard C. Mais ceux qui ont connu Python, par exemple, doivent croire que tout langage vient avec une bibliothèque standard aussi fournie.
Comme tu l'as dit, depuis l'arrivée de opam on peut toujours trouver une bibliothèque qui correspond au besoin. Au fond le dépôt opamest la bibliothèque standard. ;-)
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
Autre point que je n'ai pas mentionné, c'est la bibliothèque standard. Celle de base, fournie par INRIA, est souvent jugée limitée : elle est surtout développée pour le compilateur. Néanmoins, la société Jane Street a développé la bibliothèque core pour remédier à ce problème. C'est celle qui est utilisée dans les exemples du livre Real World OCaml.
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
Le système OCaml est une implémentation de qualité industrielle de ce langage, comprenant un compilateur produisant du code natif de haute performance (ocamlopt) pour 9 architectures de microprocesseurs (IA32, PowerPC, AMD64, Alpha, Sparc, Mips, IA64, HPAA, StrongArm), un compilateur code-octet (ocamlc) et une boucle d'interaction (ocaml) pour la rapidilité du développement et la portabilité. La distribution d'OCaml offre également une bibliothèque standard, un débogueur (ocamldebug), des générateurs d'analyseurs lexicaux (ocamllex) et syntaxiques (ocamlyacc), un pre-processeur pretty-printer (camlp4) et un générateur de documentation (ocamldoc).
Pour le second (QT5) je ne sais pas. Je n'ai rien trouvé dans les dépôts opam (le gestionnaire de paquets haute performance OCaml) mais tout ne s'y trouve pas.
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
Tu es un peu dur, même si tu n'as pas complètement tort : on trouve des personnes qui présentent ainsi le langage à des non initiés, ce qui les fait fuir inéluctablement.
Pour les messages d'erreurs, je viens de faire dans mon toplevel :
et le "1" est souligné pour indiquer qu'elle est l'expression qui n'a pas de le bon type.
Pour ce qui est de l'apprentissage, je conseille le livre de Sylvain Cochon et Jean-Christophe Filliâtre Apprendre à programmer en OCaml. Ils sont enseignants-chercheurs, et enseigne la programmation OCaml au niveau licence, donc sans tous les gros mots. ;-)
Le livre présente progressivement les concepts du langage et débute d'ailleurs par des traits purement impératifs comme les boucle for, les tableaux, les boucles while pour n'aborder qu'ensuite les spécificités du paradigme fonctionnel.
Les deux auteurs ont d'ailleurs une approche intéressante du paradigme fonctionnel qui consiste essentiellement dans la persistance des données. Ils ont, par exemple, publié ensemble un article A Persistent Union-Find Data Structure où ils exposent leur implémentation de l'algorithme union-find en utilisant des traits impératifs du langage, bien que la structure obtenue soit persistante. Là où un langage fonctionnelle pure, comme Haskell, aurait recours à des monades. Et dans leur livre il y a tout un chapitre, par exemple, où ils reprennent le concept de tableaux persistants, dont le code suit, en l'expliquant pas à pas :
Les opérations set et get sont en temps constant tant que l'on n'utilise pas le côté persistant, mais on paye un léger prix lorsque l'on veut l'utiliser (il faut défaire les patch de la version courante pour revenir à la version que l'on souhaite manipuler, c'est le rôle de la fonction reroot).
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
Preuve irrefutable: une bonne partie de l'ortographe ou de la grammaire n'apparait absolument pas a l'oral.
Dont acte: l'ecrit n'est qu'une norme abstraite, sans logique, et sans utilite reele sinon a se faire coire intelligent ceux qui l'ont appris par coeur.
On nous dit « il faut inculquer aux jeunes l’esprit scientifique ». Très bien, mais qu’est ce que ça veut dire au juste, au-delà d’une incantation un peu creuse ? Inculquer l’esprit scientifique ne se fait pas à coup de bourrage de crâne de connaissances scientifiques rebutantes, ce qui est au contraire la meilleure manière de faire fuir les élèves. De toutes façons, la science moderne est trop vaste et trop complexe pour que quiconque puisse tout connaître, on n’aura plus de Pic de la Mirandole, et c’est aussi bien. Par contre, on peut susciter la curiosité des élèves en mettant en valeur les figures de rhétorique développées par la science pour acquérir ces connaissances. Pour avoir prononcé ce terme de rhétorique devant vous, je devrais m’excuser, c’est un terme vieillot. Autrefois, il y avait des classes de rhétorique, et la notion de débat intellectuel était valorisée. Maintenant c’est terminé, on inculque des connaissances prédigérées, et la Science est imposée comme un prêche. On apprend par cœur des formules que l’on fait réciter, les exercices sont calibrés pour être résolus par application mécanique d’un cours bien saucissonné, l’esprit critique n’est pas encouragé. Ouvrons la fenêtre, discutons des méthodes qui permettent de raisonner droit, de comprendre comment poser des hypothèses, d’élaborer des conjectures, de chercher des contre-exemples. Ces méthodes sont transversales à toutes les matières enseignées, littéraires comme scientifiques. Il y a là un lien important entre philosophie et informatique, car la méthodologie informatique prolonge la rhétorique traditionnelle en tant que moyen légitime d’acquérir des connaissances. Ce sont ces préoccupations qui ont développé la logique, qui a finalement quitté la philosophie pour s’intégrer aux mathématiques, mais a perdu en passant sa finalité argumentative, qui est l’essence de la démarche scientifique. […]
Je vais prendre un autre exemple dans un domaine complètement différent, c’est l’analyse grammaticale dans la classe de français. Je ne sais pas si on fait encore beaucoup ça, mais de mon temps on décortiquait les phrases : toute phrase doit avoir un verbe, tout verbe doit avoir un sujet. Là, il y a un petit bout de raisonnement aussi. Comment est-ce que l’on obtient une phrase à partir d’un verbe ? Prenons d’abord un verbe intransitif. Un verbe intransitif a besoin d’un sujet pour exprimer son action. Donc, vous pouvez voir le rôle fonctionnel de ce verbe comme utilisant le syntagme nominal représentant le sujet pour construire la phrase représentant l’action. De même, un verbe transitif peut être vu comme une fonction qui prend son complément d’objet pour construire un syntagme verbal, se comportant comme un verbe intransitif. Vérifier que « le chat mange la souris » est une phase correcte devient un petit raisonnement où le verbe « mange » prend la souris pour construire « mange la souris », objet fonctionnel qui peut maintenant manger le chat, si je puis dire, pour donner la phrase. Le petit arbre de raisonnement, qui exprime la composition des deux fonctions en vérifiant leurs types, hé bien, c’est ce qu’on appelle l’analyse grammaticale de la phrase. Regardez de près, vous vous rendez compte que c’est exactement le même raisonnement que celui pour la machine à laver du cours de physique, avec deux étapes de modus ponens. L’analyse dimensionnelle devient l’analyse grammaticale. C’est important, en exhibant les procédés rhétoriques similaires on abstrait le raisonnement commun, pour lequel les deux disciplines fournissent des exemples concrets. Les deux exemples s’éclairent l’un l’autre, et on retient un procédé cognitif général qui peut servir pour toutes sortes d’autres investigations. En exhibant le procédé rhétorique commun, et en le réifiant dans deux disciplines supposées étanches l’une à l’autre, on apprend aux élèves que l’esprit scientifique transcende les matières enseignées et les présente comme des aventures intellectuelles cohérentes. Et puis, cela peut donner des idées. En classe de français on faisait de l’analyse grammaticale, mais on n’en faisait pas en classe d’anglais. Pourquoi ? Le même type de raisonnement s’applique, et on montre deux exemples du même phénomène, qui est ainsi mieux mémorisé. Par contre il y a des détails de grammaire qui ne sont pas les mêmes. Par exemple, en introduisant les paramètres morphologiques, on va pouvoir exprimer l’accord du verbe avec son sujet comme une contrainte sur les arbres d’analyse. En français comme en anglais. Par contre, l’adjectif est invariable en anglais, et donc ne s’accorde pas avec le nom qu’il qualifie. En mettant en lumière ces différences structurelles fondamentales, on éclaire les difficultés rencontrées par les élèves, les faux amis, les analogies erronées qui sont difficiles à déraciner. C’est important de le montrer en contraste avec le français. Parce que si vous leur apprenez l’analyse grammaticale du français, il y a une grande partie qu’ils vont pouvoir appliquer à l’anglais aussi, et les parties où cela ne s’applique pas, c’est justement les endroits où il faut faire attention à ne pas calquer d’une langue sur l’autre.
voir le texte aux pages 20 à 23
En d'autres termes, l'analyse grammaticale et morphologique d'une langue en révèle sa structure logique : comme le coup du verbe transitif qui revient à un double usage du modus ponens (si A alors B, or A, donc B). Pour illustrer cette exemple et son lien avec la logique et l'informatique (en réalité la théorie des types), je vais le coder (simplement) en OCaml
Alors assurément, la logique de la langue française (son système de type et de déclinaison) est plus sophistiqué que ce que je viens de coder, mais c'était pour illustrer autrement mon propos et celui de M. Huet. Donc non ! la grammaire n'a rien, mais absolument rien d'illogique. Bien au contraire, l'étude de la grammaire aiguise la compréhension de la logique, la montre sous un autre jour et évite de rester dans une compréhension étriquée de celle-ci.
J'avais d'ailleurs cité le même texte dans la dépêche où l'auteur de grammalecte (outil d'aide automatisée à la correction grammaticale) faisait une demande de financement participatif, afin de montrer que le problème algorithmique d'un tel outil est analogue à de l'inférence de type et à la correction automatique de démonstration. Et de fait, lorsque des grammairiens construisent un arbre d'analyse syntagmatique, la structure est très proche d'un AST ou Arbre de Syntaxe Abstrait.
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
Nan mais arrête, tu joues carrément avec l'écrit là !
Pour nous recentrer sur le sujet de l'article, et ne point prolonger le hors-sujet, on peut bien reconnaître que jouer avec les mots comme ne pas respecter leur orthographe sont bien des licences de penser que l'on peut accorder à tout un chacun. Question : sont-elles incompatibles ? doit-on s'attendre à un procès entre les deux parties en présence (surtout si l'on en vient aux mains) ou peut-on espérer un accord à l'amiable ?
Tu serais pas un « petit nobliaux fils de bourgeois trop con toi » ?
L'administration fiscale a encore moins d'humour. On a retrouvé, dans les archives de la police de Paris, deux lettres de Boris Vian à son percepteur, dont la seconde est :
Mon Cher Contrôleur,
Je suis un grand feignant, mais j'y comprends rien dans tous ces bouts de papier impossibles. Voilà ma déclaration, il y a un peu de retard; mais je suis plein de bonnes intentions.
Encore mille excuses pour ce retard excusable et répandez mes bénédictions autour de vous.
Je ne sais si le choix orthographique pour « feignant » a été relevé par le destinataire, mais le policier qui archiva les lettres nota dans son rapport : « On affirme que ces deux lettres, dont la dernière était rédigée sur l'imprimé de déclaration de revenus, auraient coûté, du point de vue fiscal, très cher à leur auteur. » source
Vian était sans doute un petit nobliaux fils de bourgeois cherchant à échapper à l'impôt.
:-)
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
J'aime beaucoup cet exemple simple :
- Allons manger grand-mère.
- Allons manger, grand-mère.
Les deux sont syntaxiquement corrects, mais ne veulent pas du tout dire la même chose !
Tout est question de personnage : cela dépend si l'on est le petit chaperon rouge ou le grand méchant loup; ce dernier ayant tout intérêt à entretenir la confusion. :-)
Hors les problématiques de ponctuation, les accents sont aussi porteur de sens et une erreur peut tout autant prêter à confusion. Par exemple, il y a des jours où je me demande si notre gouvernement croît en incompétence, ou bien s'il croit en incompétence. Quoique, dans une forme fléchie, cela permet d'assimiler la croissance à de la croyance. :-Þ
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
[^] # Re: Pour quel coût?
Posté par kantien . En réponse au journal L'increvable. Évalué à 2. Dernière modification le 25 mars 2016 à 17:07.
Ce n'est pas de lui dont il parlait dans le commentaire juste en-dessous ? Comme il se met à jouer au philosophe, j'ai cru qu'il s'était remémorer l'injonction socratique : « Connais-toi toi même ! ». Telle était l'inscription sur le temple de Delphes, temple dont l'oracle (la pythie) aurait répondu à Chéréphon qu'il n'y avait pas d'homme plus sage que Socrate dans la cité athénienne. S'interrogeant sur le sens d'une telle parole, ce dernier serait arrivé à cette conclusion : « tout ce que je sais, c'est que je ne sais rien ». Entendre par là, non qu'il était ignorant, mais contrairement à tous les sophistes qui se prétendaient les détenteurs de la sagesse, et par leur rhétorique trompaient le peuple d'Athènes, lui, Socrate, ne prétendait pas savoir ce qu'il ignorait, et que sa sagesse consistait en une quête perpétuelle vers la Vérité et le Bien — qu'il ne prétendait pas posséder. Du moins, tel est le Socrate que nous a décrit Platon.
À moins que notre seigneur du temps, le Doc. who — lui qui a vu tant de choses qu'aucun humain ne peut imaginer — pousse l'analogie socratique jusqu'à considérer que, tel le peuple athénien et la démocratie athénienne, le peuple linuxfrien le condamne à mort, sous la forme de moinsage répété, parce qu'il remettrait trop en cause, publiquement, la doxa admise dans nos rangs. Néanmoins, Socrate ne s'était jamais abaissé à insulter ses interlocuteurs. De plus, en ce jour de vendredi Saint, Jésus le Maître de L'Évangile — dont la doctrine fût qualifiée par Nietzsche de « platonisme pour la plèbe » — subit le même sort que Socrate. Et face à ses disciples qui se désolaient de le voir ainsi traiter et agoniser sur la croix, il leur dit : « Pardonnez leur, ils ne savent pas ce qu'ils font. » On est, là encore, bien loin de l'arrogance, de la suffisance, de l'insulte et bien plus proche de la sagesse.
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
[^] # Re: Traduction faite
Posté par kantien . En réponse au journal Comment devenir programmeur. Évalué à 2. Dernière modification le 25 mars 2016 à 01:11.
Ah la mathésis universalis ou la caractéristique universelle de Leibniz ! Elle en a fait couler de l'encre :
Elle fût effectivement remise au goût du jour par Frege et son idéographie, suivi par Russell. Néanmoins, je considère que les résultats d'incomplétude de Gödel (ou son équivalent informatique : le problème de l'arrêt) ont mis un terme définitif à la quête d'une telle langue. Comme le disait Wittgenstein : « ce que le langage signifie, cela ne se dit pas, cela se montre ». Mais, les enfants et héritiers qui ont creusé et retourné dans tous les sens ce sont effectivement retrouvés plus riches de la fécondité de leur champ : ce n'est point ici que l'on soutiendra le contraire. ;-)
Et puis ces recherches ont grandement inspiré le
-calcul, et donc tous les langages avec paradigme fonctionnel : Lisp, Scheme, Clojure, Haskell, OCaml… et quoi que de mieux que ce paradigme pour incarner la théorie kantienne du schématisme (cf. Critique de la Raison Pure) et comprendre ce qu'un kantien entend derrière le concept de schème. \o/
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
[^] # Re: Pour quelcoût?
Posté par kantien . En réponse au journal L'increvable. Évalué à 3.
L'introspection lucide est le premier pas vers la sagesse.
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
[^] # Re: mandatory link
Posté par kantien . En réponse au journal L'increvable. Évalué à 3. Dernière modification le 23 mars 2016 à 11:57.
Tout à fait, et c'est une des raisons pour lesquelles même si l'offre apparaissait sur le marché elle ne satisferait pas nécessairement la demande.
Je voulais juste souligner que l'objection de reynum n'était rien d'autre qu'un non sequitur, et qu'il n'est pas difficile d'expliquer la nature des offres disponibles autrement que par l'existence d'un complot généralisé sur l'obsolescence programmée (avec un cartel en arrière plan pour justifier la non apparition d'un concurrent) : le principe que tu invoques, reposant sur une contrainte du consommateur, pouvant servir à cela.
Finalement, tant les producteurs que les consommateurs ne sont pas des idiots et ne limitent pas leurs calculs et raisonnements économiques au seul bilan comptable.
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
[^] # Re: mandatory link
Posté par kantien . En réponse au journal L'increvable. Évalué à 2.
Et encore, dans le commentaire ci-dessus, je n'ai pas pris en compte le volume des ventes. L'entreprise pourrait toujours baisser sa marge par collant (à l'unité), mais accroître son bénéfice total par hausse du volume des ventes (si l'offre était réellement présente, elle écraserait la concurrence et augmenterait considérablement son volume de vente).
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
[^] # Re: mandatory link
Posté par kantien . En réponse au journal L'increvable. Évalué à 4.
D'autant que dans l'exemple hypothétique étudié dans l'article, après étude de marché l'entreprise qui fabrique les collants a constaté que les clientes potentielles sont prêtes à débourser 104€ par an pour leurs collants. Alors entre 52€ et 104€, il y a encore de la marge, elle pourrait augmenter encore un peu pour amortir le coût des éventuelles garanties et rester toujours nettement moins chers que la concurrence qui est à 104€. Non décidément, si un tel concurrent n'apparaît pas sur le marché c'est :
Pour moi, le commentaire auquel tu réponds est écrit par une personne, certainement pas décérébrée, mais qui ne comprend pas grand chose à l'économie.
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
[^] # Re: C'est bien dommage
Posté par kantien . En réponse au journal C++17 est sur les rails. Évalué à 1.
Effectivement j'ai parlé trop vite, flambda fait de même pour ne pas changer la sémantique d'évaluation, même si les deux compilateurs (le classique et le flambda) comprennent que l'expression finira dans la première branche. Ils inlinent et suppriment même le test, mais évaluent quand même les expressions à cause des effets de bord qu'elles contiennent. En revanche en l'absence d'effet de bord, c'est compilé comme pour les macros en Common Lisp.
Après que les macros offrent toutes les possibilités que tu décris, je ne le nie pas : cela permet de gérer deux stratégies différentes de beta-réduction sur les
-termes. À l'exécution en commençant par les paramètres sur les fonctions, ou à la compilation sur le corps de la macro. Là où pour l'instant OCaml ne dispose que de la première stratégie, même si l'inlining a fortement à voir avec la seconde. Ce sont deux approches du
-calcul qu'il est intéressant de comparer, même si je ne lâcherai pour rien au monde la puissance du système de types d'OCaml (statique et très grande expressivité). Le système de
-calcul typé le plus puissant étant Coq comme je l'avais expliqué ici : un programme Coq qui compile est garanti sans bug, comme le compilateur CompCert (le seul à ma connaissance) développé par Xavier Leroy, le BDFL OCaml.
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
[^] # Re: C'est bien dommage
Posté par kantien . En réponse au journal C++17 est sur les rails. Évalué à 1.
Oui c'est plus clair, je n'avais pas fait attention à ta remarque qui expliquait que les macros étaient exécutées à la compilation (ce qui explique leur dénomination).
En fait le compilateur OCaml fait la même chose avec certaines fonctions, et dans la nouvelle version à venir il le généralise via une nouvelle représentation intermédiaire, qui ne sera qu'optionnelle pour cette version, mais sera sans aucun doute la base pour les versions ultérieures. Par exemple le compilateur actuel remplace systématiquement les appels à ma fonction
iff
parif b then e1 else e2
(comme si c'était une macro en Common Lisp), mais le nouveau système pousse l'idée plus loin en l'étendant aux fonctions récursives et en « exécutant » au maximum le code de la fonction qu'il développe. Tu pourras en lire plus sur la partie que j'ai consacré, avec chicco, au système FLambda dans la dépêche en cours de rédaction.Sinon
if
est aussi une primitive en OCaml, comme en Common Lisp, mais n'est en fait qu'un cas particulier d'une autre structure primitive le pattern matching qui est une version généralisée de ta macrocond
:if b then e1 else e2
n'est qu'un alias pourmatch b with true -> e1 | false -> e2
, et on peut mettre autant de cas que l'on veut dans l'analyse et pas seulement en faisant des tests sur les booléens mais sur la forme et la structure du type que l'on étudie. Cela parce que, comme pour Common Lisp, toutes les valeurs sont essentiellement des références (sauf les typesint
,bool
,char
et les constructeurs constants comme la liste vide) et accessible uniquement via leur constructeur de type.Par exemple pour définir la fonction
list_map
qui applique une fonction à tous les éléments d'une liste, on l'écriraSinon pour la coloration de code en Common Lisp, je mets lisp comme langage.
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
[^] # Re: C'est bien dommage
Posté par kantien . En réponse au journal C++17 est sur les rails. Évalué à 1.
D'accord, si je comprends bien ce qui distingue une fonction d'une macro c'est le mode d'évalution des paramètres : pour une fonction ils sont passés par valeur, là où pour une macro ils sont passés par nom (dans ce cas l'évaluation est-elle paresseuse, i.e évalué une seule fois à la première utilisation du terme, ou recalculer à chaque usage du terme ?).
Comme l'a dit anaseto, en OCaml les paramètres sont passés par valeur, ils sont évalués par l'appelant avant d'être passés à la fonction appelée (à la manière des fonctions Lisp et non des macros). La seule exception concerne les opérateurs sur les booléens : && (et) et || (ou) qui sont évalués de gauche à droite et de façon paresseuse. Cela étant en Comme Lisp
if
est une macro ou une fonction ?Comme l'a aussi précisé anaseto, il est possible de faire de l'évaluation paresseuse en OCaml via le module
Lazy
. Le même exemple (factoriel) aveciff
en mode macro :Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
[^] # Re: Intérêt d'un truc pareil ?
Posté par kantien . En réponse au journal "Meilleur dev de France" ?. Évalué à 4.
Oui, cette image convient parfaitement aussi. :-)
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
[^] # Re: C'est bien dommage
Posté par kantien . En réponse au journal C++17 est sur les rails. Évalué à 3. Dernière modification le 18 mars 2016 à 17:34.
Effectivement je ne connaissais pas la terminologie Lisp, une macro n'est rien d'autre qu'une fonction si je comprend bien ? ou sont-ce des fonctions d'une forme particulière ? De fait la syntaxe Lisp représente directement son AST, là où en OCaml on passe par des modules du compilateur pour le manipuler. Mais il me semble que c'est essentiellement pour des raisons de typage : le Lisp est du lambda-calcul faiblement typé, là où OCaml est du lambda-calcul fortement typé statiquement.
Après le lambda-calcul est certes un outil essentiellement théorique (utile pour la théorie des langages), mais c'est juste du Lisp encore plus fruste : il n'y a qu'un seul opérateur, à savoir
lambda
, et on ne peut pas donner de nom aux termes (il n'y a pas d'opérateur d'affectation commedefun
oulet
). Par exemple((lambda x) (x))
est la fonction identité ou encore((lambda x) (y))
est la fonction constante égale ày
. Ainsi si on applique le premier terme à n'importe quoi (n'importe quelle s-expression dont le seul opérateur de construction estlambda
) alors il le renvoie, du genre(((lambda x) (x))((lambda z) (u v)))
s'évalue en((lambda z) (u v))
.Sinon, on peut aussi coder du OCaml à la manière de Lisp en notation purement préfixée. Il suffit d'entourer un opérateur infixe par des parenthèses pour l'utiliser en préfixe comme dans
( + ) 1 2
qui vaut3
.Exemple sur la fonction factorielle en récursif terminal :
dans le même style en OCaml
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
[^] # Re: C'est bien dommage
Posté par kantien . En réponse au journal C++17 est sur les rails. Évalué à 3. Dernière modification le 18 mars 2016 à 11:34.
Tu as bien compris, et l'intérêt de passer par des outils propres aux compilateurs pour étendre la syntaxe plutôt que d'utiliser des macros c'est :
Jusqu'à il y a deux ans, pour étendre la syntaxe OCaml on utilisait un pré-processeur
camlp4
(ce qui, au fond, est similaire à de la macro) mais c'était chiant à écrire et on se retrouvait avec des tonnes de syntaxes différentes entre les projets : la coopération entre projet était rendue plus compliqué. Avec la nouvelle façon de faire, viappx
, cela se passe au niveau de la manipulation des AST et les extensions sont uniformisées : la coopération est simplifiée et s'est accrue. Par exemple dans le cas de Eliom :Étendre la syntaxe d'un langage est une chose fort utile, mais il ne faut pas que cela défigure complètement la syntaxe initiale (ce qui est tentant avec les macros) et quitte à générer du code par modification de la syntaxe autant le faire au niveau de l'AST : ce que montre la signature du foncteur que tu cites (une signature en OCaml c'est l'équivalent des headers en C ou C++, et un foncteur est proche des templates du C++ : une fonction dont les paramètres sont des modules, i.e. des structures ayant une signature donnée).
Les foncteurs (comme les templates en C++) est aussi une manière beaucoup plus simple et sécurisée (meilleur contrôle du typage) de générer du code. Un exemple simple, en OCaml, et la cas de la structure d'ensemble : pour construire des ensembles sur un type de donné quelconque, il suffit de le munir d'une relation d'ordre et d'utiliser le foncteur
Set.Make
Pour ce qui est du parenthésage, c'est une question de goût, mais la syntaxe de Lisp qui colle à la syntaxe du lambda-calcul n'est pas toujours des plus simples à lire. Par exemple la fonction qui consiste à échanger l'ordre d'application des arguments d'une fonction s'écrit en
-calcul :
z.(
x.(
y.(z y)x)), là où je trouve la syntaxe
let swap z x y = z y x
plus « parlante » et moins « lourde ».Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
[^] # Re: C'est bien dommage
Posté par kantien . En réponse au journal C++17 est sur les rails. Évalué à 2.
Cela ressemble à ocsigen ce que tu décris, en moins développé. C'est écrit en OCaml (c'est la même famille que Lisp :
-calcul avec très impératif, et aussi objet, mais en mieux typé et sans les horreurs du paranthésage et des macros — pour moi, avoir besoin de macros est un défaut de conception dans un langage) et ça génère du html garanti conforme (grâce au système de types du langage) ainsi que de la compilation OCaml vers javascript : ce qui permet d'écrire une webapp en full-ocaml en codant les parties client et serveur dans le même langage, tout en bénéficiant de la puissance et de la sécurité de son système de types.
En exemple, tu as l'application graffiti : proof of concept d'une application collaborative de dessin (si tu ouvres deux navigateurs sur la page, ce que tu dessines dans l'un est répercuté sur le caneva de l'autre) dont le code fait 200 lignes.
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
[^] # Re: Hôpital … charité
Posté par kantien . En réponse au journal Sale temps pour les informaticiens lanceurs d'alerte. Évalué à -3.
Le courage est-il un attribut qui n'est caractéristique que des personnes possédant une paire de couilles ? Le courage serait-il un attribut exclusivement masculin ? La phrase aurait eu le même sens, et la même portée en la formulant : « On a toujours le choix, mais on n'a pas toujours le courage qui va avec ! » (j'y ai simplement substitué ton expression, quelque peu phallocrate, par un point d'exclamation — je suppose qu'elle avait pour but de souligner la détermination inébranlable que nécessite le courage).
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
[^] # Re: Machine Learning
Posté par kantien . En réponse au journal AlphaGo remporte le premier match contre Lee Sedol. Évalué à 3. Dernière modification le 10 mars 2016 à 17:54.
Assurément que de base le programme savait déjà bien jouer au Go. Je rappelle pour cela le koan de Marvin Minsky :
:-)
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
[^] # Re: Pourquoi ?
Posté par kantien . En réponse à la dépêche Swift sous GNU/Linux - Introduction. Évalué à 4.
Effectivement, à ce niveau tu as raison. Il me semble aussi qu'ils travaillent dessus, ce qui est d'ailleurs plus une question de temps à consacrer au sujet que de difficultés. À mon avis, si ce n'est pas encore présent c'est que ceux qui s'occupent du compilateur bossent tous sur Emacs et que leurs extensions résolvent déjà ce problème, donc de leur seul point de vue il n'existait pas.
Le
if
peut bien servir de temps en temps (test d'égalité physique ou structurelle) mais assurément le pattern matching est le cœur d'un code OCaml. Mais l'ouvrage que je citais amène bien évidemment tous ces concepts (pour preuve l'exemple de code que j'ai cité) mais dans une approche progressive que je trouve bien faite sur le plan pédagogique. Et l'on n'y trouve pas tous les gros mots que tu as cités : monades, type algébrique, clôture, currification… ou du moins pas d'entrée de jeu. Il n'y est jamais question de monade (c'est indispensable en Haskell pour les IO, mais pas en OCaml) ni de clôture (il me semble), et ils parlent un peu de types algébriques et de currification (c'est indispensable) mais sans rentrer dans le détail : c'est inutile, il vaut mieux apprendre par l'exemple. Mais l'on aborde des techniques évoluées du langage comme la fonctorisation.Pour revenir sur la non-nécessité des monades en OCaml, qui reste pour moi le concept le plus abstrait et sans doute le plus dur à comprendre dans ta liste, je vais revenir sur le code que j'avais cité en exemple. Au fond ce qu'ils codent pour avoir des tableaux persistants c'est un système de contrôle de version sur des tableaux : faire un
set
c'est faire un commit sur la structure et la fonctionreroot
a pour rôle de se rebaser sur le tableau sur lequel on veut opérer : on modifie le graphe desdiff
jusqu'à ce que notre tableau soit à la base et un « véritable » tableau. Et pour faire cela, ils manipulent des pointeurs ce qui est impossible en fonctionnel pur à la Haskell. Néanmoins pour l'utilisateur d'une telle structure de données, on lui présentera cette interface dans le fichier.mli
:La fonction
reroot
fait partie de la machinerie interne (du point de vue du mathématicien, c'est un lemme qui n'a pas besoin d'être connu de l'utilisateur), la représentation concrète du type lui est cachée (il ne peut donc pas manipuler les pointeurs) et pour lui tout ce passe comme si c'était du fonctionnel. C'est pour cela que les auteurs aiment bien définir ainsi une des caractéristiques du paradigme fonctionnel :Et effectivement la structure des tableaux persistants fonctionne avec des effets de bord (les fonctions
set
etreroot
) mais cela c'est en interne et l'utilisateur ne l'observe pas : pour lui la structure est persistante.Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
[^] # Re: Backup
Posté par kantien . En réponse au journal Comment Github a ressuscité mon logiciel libre. Évalué à 2.
Oui, c'est le principe de précaution et il fait partie de notre Constitution depuis Chirac : de peur que ce soit mal un jour, on n'utilise pas ! :-/
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
[^] # Re: Pourquoi ?
Posté par kantien . En réponse à la dépêche Swift sous GNU/Linux - Introduction. Évalué à 3.
Si c'est juste pour avoir un serveur web, il y a ocsigen server. Après les tutos sont surtout là si tu veux faire une webapp en full-OCaml avec le framework eliom qui permet de coder les parties clients et serveurs en même temps. Et 200 lignes de code pour faire une appli simple de dessin collaboratif, c'est pas mal je trouve.
Qu'entends-tu par « il n'utilise pas du OCaml standard » ? Est-ce l'usage de fichier
.eliom
? Cela est du à la nécessité de compiler différemment les code clients et serveurs que l'on met dans le fichier entre les balises[%%client]
,[%%server]
ou[%%shared]
, mais entre ces balises c'est bien du OCaml standard.Sinon il y a aussi cohttp développé par l'équipe de mirage.
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
[^] # Re: Pourquoi ?
Posté par kantien . En réponse à la dépêche Swift sous GNU/Linux - Introduction. Évalué à 5.
Je suis bien d'accord avec toi, mais je l'ai souvent entendu c'est pour cela que je l'ai précisé. Et effectivement, elle est bien plus fournie que la bibliothèque standard C. Mais ceux qui ont connu Python, par exemple, doivent croire que tout langage vient avec une bibliothèque standard aussi fournie.
Comme tu l'as dit, depuis l'arrivée de
opam
on peut toujours trouver une bibliothèque qui correspond au besoin. Au fond le dépôtopam
est la bibliothèque standard. ;-)Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
[^] # Re: Pourquoi ?
Posté par kantien . En réponse à la dépêche Swift sous GNU/Linux - Introduction. Évalué à 2.
Autre point que je n'ai pas mentionné, c'est la bibliothèque standard. Celle de base, fournie par INRIA, est souvent jugée limitée : elle est surtout développée pour le compilateur. Néanmoins, la société Jane Street a développé la bibliothèque core pour remédier à ce problème. C'est celle qui est utilisée dans les exemples du livre Real World OCaml.
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
[^] # Re: Pourquoi ?
Posté par kantien . En réponse à la dépêche Swift sous GNU/Linux - Introduction. Évalué à 1. Dernière modification le 09 mars 2016 à 19:15.
Pour le premier point OCaml le fait :
Pour le second (QT5) je ne sais pas. Je n'ai rien trouvé dans les dépôts opam (le gestionnaire de paquets haute performance OCaml) mais tout ne s'y trouve pas.
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
[^] # Re: Pourquoi ?
Posté par kantien . En réponse à la dépêche Swift sous GNU/Linux - Introduction. Évalué à 5.
Tu es un peu dur, même si tu n'as pas complètement tort : on trouve des personnes qui présentent ainsi le langage à des non initiés, ce qui les fait fuir inéluctablement.
Pour les messages d'erreurs, je viens de faire dans mon toplevel :
et le
"1"
est souligné pour indiquer qu'elle est l'expression qui n'a pas de le bon type.Pour ce qui est de l'apprentissage, je conseille le livre de Sylvain Cochon et Jean-Christophe Filliâtre Apprendre à programmer en OCaml. Ils sont enseignants-chercheurs, et enseigne la programmation OCaml au niveau licence, donc sans tous les gros mots. ;-)
Le livre présente progressivement les concepts du langage et débute d'ailleurs par des traits purement impératifs comme les boucle for, les tableaux, les boucles while pour n'aborder qu'ensuite les spécificités du paradigme fonctionnel.
Les deux auteurs ont d'ailleurs une approche intéressante du paradigme fonctionnel qui consiste essentiellement dans la persistance des données. Ils ont, par exemple, publié ensemble un article A Persistent Union-Find Data Structure où ils exposent leur implémentation de l'algorithme union-find en utilisant des traits impératifs du langage, bien que la structure obtenue soit persistante. Là où un langage fonctionnelle pure, comme Haskell, aurait recours à des monades. Et dans leur livre il y a tout un chapitre, par exemple, où ils reprennent le concept de tableaux persistants, dont le code suit, en l'expliquant pas à pas :
Les opérations
set
etget
sont en temps constant tant que l'on n'utilise pas le côté persistant, mais on paye un léger prix lorsque l'on veut l'utiliser (il faut défaire lespatch
de la version courante pour revenir à la version que l'on souhaite manipuler, c'est le rôle de la fonctionreroot
).Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
[^] # Re: Un potentiel sacré bourbier
Posté par kantien . En réponse à la dépêche ZFS, Canonical et GPL. Évalué à 10.
Je m'inscris en faux contre une telle affirmation. J'en veux pour preuve cette extrait d'un discours de Gerard Huet Fondements de l'informatique, à la croisée des mathématiques, de la logique et de la linguistique. lors d'un colloque sur l'enseignement philosophique et les sciences.
En d'autres termes, l'analyse grammaticale et morphologique d'une langue en révèle sa structure logique : comme le coup du verbe transitif qui revient à un double usage du modus ponens (si A alors B, or A, donc B). Pour illustrer cette exemple et son lien avec la logique et l'informatique (en réalité la théorie des types), je vais le coder (simplement) en OCaml
Alors assurément, la logique de la langue française (son système de type et de déclinaison) est plus sophistiqué que ce que je viens de coder, mais c'était pour illustrer autrement mon propos et celui de M. Huet. Donc non ! la grammaire n'a rien, mais absolument rien d'illogique. Bien au contraire, l'étude de la grammaire aiguise la compréhension de la logique, la montre sous un autre jour et évite de rester dans une compréhension étriquée de celle-ci.
J'avais d'ailleurs cité le même texte dans la dépêche où l'auteur de grammalecte (outil d'aide automatisée à la correction grammaticale) faisait une demande de financement participatif, afin de montrer que le problème algorithmique d'un tel outil est analogue à de l'inférence de type et à la correction automatique de démonstration. Et de fait, lorsque des grammairiens construisent un arbre d'analyse syntagmatique, la structure est très proche d'un AST ou Arbre de Syntaxe Abstrait.
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
[^] # Re: Un potentiel sacré bourbier
Posté par kantien . En réponse à la dépêche ZFS, Canonical et GPL. Évalué à 2.
Pour nous recentrer sur le sujet de l'article, et ne point prolonger le hors-sujet, on peut bien reconnaître que jouer avec les mots comme ne pas respecter leur orthographe sont bien des licences de penser que l'on peut accorder à tout un chacun. Question : sont-elles incompatibles ? doit-on s'attendre à un procès entre les deux parties en présence (surtout si l'on en vient aux mains) ou peut-on espérer un accord à l'amiable ?
L'administration fiscale a encore moins d'humour. On a retrouvé, dans les archives de la police de Paris, deux lettres de Boris Vian à son percepteur, dont la seconde est :
Je ne sais si le choix orthographique pour « feignant » a été relevé par le destinataire, mais le policier qui archiva les lettres nota dans son rapport : « On affirme que ces deux lettres, dont la dernière était rédigée sur l'imprimé de déclaration de revenus, auraient coûté, du point de vue fiscal, très cher à leur auteur. » source
Vian était sans doute un petit nobliaux fils de bourgeois cherchant à échapper à l'impôt.
:-)
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
[^] # Re: Un potentiel sacré bourbier
Posté par kantien . En réponse à la dépêche ZFS, Canonical et GPL. Évalué à 2.
Tout est question de personnage : cela dépend si l'on est le petit chaperon rouge ou le grand méchant loup; ce dernier ayant tout intérêt à entretenir la confusion. :-)
Hors les problématiques de ponctuation, les accents sont aussi porteur de sens et une erreur peut tout autant prêter à confusion. Par exemple, il y a des jours où je me demande si notre gouvernement croît en incompétence, ou bien s'il croit en incompétence. Quoique, dans une forme fléchie, cela permet d'assimiler la croissance à de la croyance. :-Þ
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.