kantien a écrit 1131 commentaires

  • [^] # Re: Bicamérisme

    Posté par  . En réponse au journal [HS] Déchéance de nationalité et constitutionnalisation de l'état d'urgence bronsonisés. Évalué à 2.

    Et vous, vous pensez quoi du bicamérisme ?

    Sur le principe, je dirais que cela permet peut être une meilleure représentativité des collectivités locales au niveau législatif et atténue la structure centralisée de l'État français; même si, de part ses institutions, notre État n'est pas fédéral.

    Néanmoins, l'existence du bicamérisme en France est à nouveau révélateur de la conception hollandesque de nos instituions. N'avait-il point, dans ses promesses électorales, l'extension du droit de vote aux étrangers non communautaires aux élections municipales ? Ce qui reviendrait, par le bien du suffrage indirect via le Sénat, à leur accorder un droit de regard législatif sur tout le territoire.

    Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.

  • [^] # Re: {{pas clair}}

    Posté par  . En réponse au journal [HS] Déchéance de nationalité et constitutionnalisation de l'état d'urgence bronsonisés. Évalué à 6.

    À qui tu fais référence, voulais-tu dire ? Au hasard : Christiane Taubira qui a démissionné pour désaccord profond sur la question de la déchéance de nationalité ?

    Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.

  • [^] # Re: Mauvais tableau

    Posté par  . En réponse au journal Tableur de calcul pour auto-entrepreneur 2016. Évalué à 4.

    il [vaut] mieux aller dormir à l'hôtel 100€ plutôt que de dormir gratos chez un pote car l'hôtel et déductible du revenu donc moins d'impôt (factuellement, c'est vrai… je vous laisser deviner la stupidité de la chose).
    2 exemple, venant… d'un Bac+5

    Ah oui, quand même ! Dépenser 100, pour réduire ses impôts de 20 : quel grand bénéfice !
    Tu me diras, il y a une variante de ce sophisme sur la réduction d'impôt qui est un don : tu as 100, d'habitude je te prends 30, mais là je te prends que 20, donc je te donne 10. /o\

    Pour ce qui est du niveau d'étude nécessaire, j'en parlerai à une de mes connaissances. Il a un CAP et à commencer en faisant les 3-8 chez Michelin. Pour arrondir ses fins de mois, avec des potes il installait des cuisines, des meubles chez des gens (au black). Il s'est dit : je vais monter ma boîte d'installation de cuisine. Il s'est associé avec un margoulin, ça a fait faillite. Pas de soucis, il en a remonté une mais cette fois il vend et pose des salles de bain. Et ma foi, il est plutôt satisfait de sa situation.

    Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.

  • [^] # Re: ouai

    Posté par  . En réponse au journal Données vs Code. Évalué à 1. Dernière modification le 30 mars 2016 à 12:25.

    De ce que j'ai compris du type Either en Haskell, il est identique au type Result en Elm.

    En Haskell la définition est :

    date Either a b = Left a | Right b

    en Elm, selon ton lien c'est :

    type Result error value = Ok value | Err error
    

    et en OCaml, son équivalent est :

    type ('a,'b) result = Ok of 'a | Error of 'b

    Et à l'usage, on les emploie pareil : soit le calcul s'est bien passé est on renvoie du Ok (ou Right en Haskell), soit il y a eu une erreur et on la propage via Err, Error ou Left.

    Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.

  • [^] # Re: Map-Reduce

    Posté par  . En réponse au journal Données vs Code. Évalué à 2.

    Je vois pas comment c'est possible :

    Signature minimale d'un graphe et exemples d'implémentation en OCaml

    type graph
    type vertex
    
    val iter_vertex : (vertex -> unit) -> graph -> unit
    (** Parcourt les sommets du graphe en appliquant la fonction passée en argument à chacun d'eux *)
    
    val iter_succ : (vertex -> unit) -> graph -> succ -> unit
    (** Comme l'autre mais se limite aux successeurs d'un sommet donné *)

    Quelques algorithme classiques sur les graphes : comme le parcours en largeur, le parcours en profondeur, le plus court chemin…

    Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.

  • [^] # Re: Karma négatif et comptes multiples

    Posté par  . En réponse au journal Tableur de calcul pour auto-entrepreneur 2016. Évalué à 1.

    (c'est très jésuite : si tu poses une question, c'est que tu as déjà la réponse, ce pour quoi ils répondent par une question ces cons, genre « t'es sûr ? », ils ont d'autres méthodes plus élaborées… J'en ferai un nourjal un jour, ou pas).

    Ils n'ont pas complètement tort les jésuites sur le coup, et ça me rappelle ce que nous avez dit un professeur lorsque j'étais encore étudiant : pour faire un bon chercheur, il ne faut pas seulement savoir répondre aux questions, mais savoir se poser les bonnes questions (sous-entendu que la réponse, ou le chemin qui mène à elle, se trouve déjà dans la question).

    Néanmoins, je doute qu'il fût affilié de près ou de loin à l'ordre des jésuites, nous ayant fait hurler de rire avec cette anecdote : « je lisais ce matin que le Pape [Jean Paul II à l'époque] avait sanctifié autant de personnes que tous le Papes précédents réunis. Sachant que ces dix dernières années on a publié autant d'écrits mathématiques que depuis l'Antiquité, si un jour vous écrivez un article inutile [ou un commentaire inutile sur linuxfr :-P] vous pourrez vous considérez en bijection avec un sanctifié du Pape. \o/ »

    Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.

  • [^] # Re: ouai

    Posté par  . En réponse au journal Données vs Code. Évalué à 3.

    En quoi est-ce que c'est un type abstrait ?

    Un type abstrait est un type encapsulé dans un module dont on cache la représentation concrète à l'utilisateur. Ainsi, il ne peut manipuler les données de ce types que via les fonctions exportées par le module, ce qui permet de garantir des invariants sur la structure de données (à condition que les fonctions la manipulant soient bien codées, cela va de soi ;-)

    En OCaml ça peut donner cela, avec un fichier d'interface password.mli

    type t
    val create_pwd : string -> t

    et dans le fichier qui implémente l'interface password.ml tu as

    type t = string (* le type t est un alias du type string mais l'utilisateur ne le sait pas *)
    let create_pwd s = (* mon über code générant des mots de passe *)

    et l'utilisateur ne pourra jamais manipuler les mots de passe comme des string.

    Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.

  • [^] # Re: ouai

    Posté par  . En réponse au journal Données vs Code. Évalué à 1.

    Tu devrais lire l'article de Jacques Garrigue que j'ai donnée en lien, tu devrais y trouver les réponses à tes questions.

    Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.

  • [^] # Re: ouai

    Posté par  . En réponse au journal Données vs Code. Évalué à 3.

    Comment tu composes ces contraintes (trié + pairs par exemple) si chaque contrainte donne naissance à un seul type ?

    En utilisant des variants polymoprhes pour faire de l'héritage multiple ?

    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  . En réponse au journal C++17 est sur les rails. Évalué à 1.

    Au cours des discussions qui entourent la rédaction de la dépêche, j'ai appris qu'il y avait le projet d'ajouter le principe des macros à la Lisp au langage OCaml : modular macros.

    Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.

  • # Liaison statique

    Posté par  . En réponse au journal Vivre en fascisie. Évalué à 10.

    Dans un autre journal, Benoît Sibaud avait lié dynamiquement le xkcd de rigueur. Le linker ne réalisant pas toujours parfaitement sa tâche, pourtant simple et qui consiste à suivre l'hyperlien, une liaison statique s'impose donc.

    Free Speech

    Bien conscient que la réponse du « con » Yvan Munoz est encore trop récente pour qu'elle ait pu porter ses fruits, je me permets de la rappeler :

    Pour te donner un conseil bien qu'ayant conscience qu'à ce moment il t'est inutile, espérant seulement qu'il puisse germer et donner un jour un fruit ou une fleur.

    lire la suite

    Ce qui reste tout de même étonnant dans toute cette histoire, c'est qu'une personne qui se dit victime de la censure de l'organisation tyrannique des administrateurs de DLFP puisse encore s'exprimer sur cette même DLFP. Ce sont de drôles de censeurs ces administrateurs… ;-)

    Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.

  • [^] # Re: Intérêt douteux

    Posté par  . En réponse au journal L'increvable. Évalué à 1.

    Le système européen a aussi beaucoup de mal à protéger ses intérêts économiques et certains pays industriels européens, comme la France, souffrent fortement d'une ouverture à la concurrence internationale à laquelle ils n'étaient pas correctement préparés.

    Tu sous-entends que c'est la "faute des autres", moi je tournerai la phrase comme ça : le monde change, et ces français imbus d'eux-même refusent toujours de le comprendre (faut voir les réactions en ce moment sur des propositions de loi assez légères quand on regarde de loin) et de faire ce qui aurait dû être fait il y a 10 ans, alors forcément ça coince.
    La différence entre les deux phrases (la tienne et la mienne) est que d'un côté celui qui parle sous-entend que l'autre est le méchant, et de l'autre celui qui parle regarde le problème qu'il a chez lui et qu'il peut lui résoudre.

    Le problème est plus ancien que cela et remonte, a minima, au colbertisme : sans doute une autre « exception française ». Il y a, au fond de tout cela, la funeste idée que l'économie des échanges marchands est un jeu à somme nulle : ce qu'un acteur gagne doit être perdu par un autre acteur. D'où les différentes variantes de politique protectionniste cherchant à réserver le marché intérieur à la production intérieure (« vive le made in France ! \o/ »).

    Pourtant les échanges marchands librement consentis reposent sur le principe : j'accepte de faire cela pour toi, à condition que tu fasses ci pour moi. Comment les deux parties en présence pourraient-elles accepter de contracter si l'une des deux était nécessairement le dindon de la farce, ou in fine se retrouverait gros-jean comme devant ? Je ne cherche pas à nier qu'il y a des échanges qui se passent ainsi, l'une des deux parties pouvant profiter de la faiblesse ou de l'ignorance de l'autre pour la tromper, mais une telle situation n'est pas inhérente au principe de l'échange.

    Comme pamphlet anti-protectionnisme, il y a la fameuse pétition des marchands de chandelles : quel concurrent plus sournois que le soleil peut-on imaginer face aux fournisseurs d'éclairage, lui qui refuse obstinément de se plier aux lois des hommes ?

    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  . En réponse au journal L'increvable. Évalué à 1.

    Socrate ne s'était jamais abaissé à insulter ses interlocuteurs.

    Pour affirmer une telle absurdité il faut n’avoir rien lu de Platon, ou n’être pas en capacité d’en tirer quoi que ce soit d’intelligible. Car j’ai bien en tête deux ou trois petites saillies bien senties dans ce que l’on sait du procès (tout du moins de la défense…) ou Socrate se fout le plus ouvertement du monde de ceux-là même qui le jugent (avec une arrogance qui vaut bien la mienne) : ça n’étaient effectivement pas un garçon très sage.

    Il lui arrivait bien de railler et de moquer ses interlocuteurs, et pas seulement dans sa défense et l'Apologie, mais avec une finesse d'esprit qui est à des années lumières de la tienne.

    Un grand homme ce Nietzsche.

    Au moins comprends-je maintenant le ton de ta prose et ta position sur le couple Socrate-Platon. Bien que la lecture de celle de Nietzsche soit plus intéressante et enrichissante, philosophie que j'exécre pourtant au plus haut point (on peut difficilement attendre une autre position de la part d'un kantien).

    Pour le reste, cela se passe de commentaire. Et pour compléter l'information à destination des lecteurs qui n'aurait pas lu l'Apologie de Socrate (ou tout autre dialogue platonicien), celui-ci n'était pas accusé d'être un sophiste, mais les chefs accusations étaient :

    • ne pas reconnaître les Dieux de la Cité ;
    • inventer de nouveaux Dieux pour les remplacer ;
    • corrompre la jeunesse.

    Et Socrate ne reprochait pas aux sophistes de mentir (tenir pour vrai ce que l'on sait être faux) mais de prétendre savoir ce qu'en réalité ils ignoraient. Autrement dit, il leur reprochait de ne pas s'interroger suffisamment sur le fondement de leurs affirmations, et de faire passer, entre autre, le vraisemblable pour de la certitude; de préférer dire : « je sais, telle est la vérité ! » plutôt que d'affirmer : « je ne sais pas, mais je cherche ! ». Comme par exemple, affirmer :

    Et encore! Quelques références que ce soit, on en attendra plus que de maigres citations sorties de leur contextes, archies connues tant elles ont été répétés jusqu’à plus soif. L’on peut à ce propos être certain qu’un texte qui en fait usage est tout au plus la production d’un cuistre qui se chargera le plus sûrement du monde de se mettre en contre-sens le plus total avec la pensée originelle de l’auteur.

    Alors que je n'ai fait que synthétiser certains passages de l'Apologie de Socrate. Crois-tu que je m'amuses à faire référence à des écrits que je n'ai pas lu ? Et pour illustrer, sur un exemple, l'attitude de Socrate dans son procès lorsqu'il s'adresse aux athéniens présents pour le juger :

    Ma seule affaire est d'aller et de venir pour vous persuader, jeunes et vieux, de n'avoir point pour votre corps et pour votre fortune de souci supérieur ou égal à celui que vous devez avoir concernant la façon de rendre votre âme la meilleure possible, et de vous dire : « Ce n'est pas des richesses que vient la vertu, mais de la vertu que viennent les richesses et tous les autres biens, pour les particuliers comme pour l'État. » Si donc c'est en tenant ce discours que je corromps les jeunes gens, il faut bien admettre que ce discours est nuisible. Mais prétendre que je tiens un autre discours que celui-là, c'est ne dire rien qui vaille. Au regard de cela, si je puis me permettre, Athéniens, suivez ou non l'avis d'Anytos, acquittez-moi ou non, mais tenez pour certain que je ne me comporterai pas autrement, dussé-je subir mille morts.

    N'allez pas m'interrompre en faisant du tapage Athéniens. Continuez plutôt à faire comme je vous l'ai demandé. Cessez de m'interrompre en faisant du tapage, et prêtez-moi l'oreille. J'ai tout lieu de croire que vous y trouverez profit. Sans doute ai-je encore à vous dire des choses qui vont vous inciter à m'interrompre, en faisant du tapage. De grâce, veulliez vous en abstenir.

    On est tout de même assez loin du : « bandes de crétins dégénérés, allez-vous donc enfin reconnaître votre imbécillité, votre ignorance, ma supériorité et le fait que la vérité est de mon côté ! »

    Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.

  • [^] # Re: oui github se sourceforgise :/

    Posté par  . En réponse au journal Github et la génération (pas terrible) de contenu. Évalué à 4.

    BAud a du se tromper de journal sur github, je suppose qu'il pensait à la position que zenitram a exposé dans celui-ci : le danger github.

    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  . 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.

  • [^] # Re: Traduction faite

    Posté par  . 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 :

    Deux mots seulement sur l’art de combi­ner 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 expli­quer ces principes présentent, par leur extrême sim­plicité, 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 en­foui ; 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.

    Kant, Explication nouvelle des premiers principes de la connaissance métaphysique

    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 \lambda-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  . 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  . 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.

  • [^] # Re: mandatory link

    Posté par  . 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  . 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 :

    • 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.

  • [^] # Re: C'est bien dommage

    Posté par  . En réponse au journal C++17 est sur les rails. Évalué à 1.

    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 \lambda-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 \lambda-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 \lambda-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  . En réponse au journal C++17 est sur les rails. Évalué à 1.

    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 'a list =
     | Nil (* la liste vide *)
     | Cons of 'a * 'a list (* 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 *)
    
    let rec list_map f l =
      match l with
      (* 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 -> (f hd ) :: (list_map f tl)
    ;;
    
    (* on peut alors faire une fonction qui renvoie la liste des successeurs d'une liste d'entiers *)
    let succ_list l = list_map (fun n -> n + 1) l;;
    
    (* mais à la compilation il va développer list_map comme une macro et simplifier le tout en *)
    let succ_list l =
      let rec list_map' l =
        match l with
        | [] -> []
        | hd :: tl -> (hd + 1) :: (list_map' tl)
      in list_map' l
    ;;

    Sinon pour la coloration de code en Common Lisp, je mets lisp comme langage.

    (defmacro if (condition expr1 expr2)
      `(cond
         (,condition
           ,expr1)
         (t
           ,expr2)))

    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  . 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 ?).

    Par curiosité, dans ton exemple en OCaml tu écris ça :

    (* je code le test if-then-else en fonctionnel pure *)
    let iff b e1 e2 = if b then e1 else e2

    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 :

    let le = ( <= ) and mul = ( * ) and minus = ( - );;
    val le : 'a -> 'a -> bool = <fun>
    val mul : int -> int -> int = <fun>
    val minus : int -> int -> int = <fun>
    
    (* maintenant iff n'évalue que e1 ou que e2 suivant la valeur du booléen *)
    let iff b e1 e2 = if b then Lazy.force e1 else Lazy.force e2
    val iff : bool -> 'a lazy_t -> 'a lazy_t -> 'a = <fun>
    
    let rec factorial ?(acc=1) n =
     (iff (le n 1)
        (lazy acc)
        (lazy (factorial ~acc:(mul acc n) (minus n 1)))) (* on pourrait utiliser (pred n) au lieu de (minus n 1) *)
    val factorial : ?acc:int -> int -> int = <fun>
    
    factorial 5;;
    - : int = 120

    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  . En réponse au journal "Meilleur dev de France" ?. Évalué à 4.

    quelle image choisir pour tous ceux qui perpétuent ces organisations défaillantes ? Pisseurs de powerpoint ?

    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  . 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 :

    (defun factorial (n &optional (acc 1))
      (if (<= n 1)
          acc
        (factorial (- n 1) (* acc n))))

    dans le même style en OCaml

    (* je commence par renommer les opérateurs infixes sous forme préfixe *)
    let le = ( <= ) and mul = ( * ) and minus = ( - )
    
    (* je code le test if-then-else en fonctionnel pure *)
    let iff b e1 e2 = if b then e1 else e2
    
    (* maintenant je code à la Lisp *)
    let rec factorial ?(acc=1) n =
    (* pour des raisons de typage on rajoute le mot clé rec et le paramètre optionnel est en premier *)
    
     (iff (le n 1)
        acc
        (factorial ~acc:(mul acc n) (minus n 1)))
    
    (* en OCaml plus idomiatique cela donnerait *)
    let factorial n =
      let rec loop acc n =
        match n with
        | 1 -> acc
        | _ -> loop (acc * n) (n - 1)
      in loop 1 n

    Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.