• # J'ai pas écouté le podcast, mais mon grain de sel

    Posté par  (site web personnel) . Évalué à 8.

    Dans le domaine du jeu vidéo, on voit apparaître depuis 10-15 ans un retour vers la programmation fonctionnelle (qui est très vieille), notamment avec le concept de Data-Oriented Design et les Entity Component System.

    La programmation orienté objet s'est faite malmenée en entreprise. J'entends par la que les paradigmes initiaux ont été détourné de telle sorte qu'elle ne tient plus ses promesses (réutilisation du code).

    J'en profite pour citer sans connaître l'auteur original :

    En POO, si tu veux une banane, tu dois ajouter le gorille qui tient la banane et toute la forêt.

    Sauf que POO et Programmation Fonctionnelle ne sont pas incompatible. Prenons l'exemple de Go (ugh, qu'est-ce que je déteste ce langage trop pratique…). Il y a des interfaces, des structures, des méthodes. Pas d'héritage, que de la composition. C'est suffisant pour implémenter de l'injection de dépendance, pattern très utilisé en programmation fonctionnelle pour découpler le business code de l'implémentation.

    Les ECS en gamedev sont aussi une forme d'injection de dépendance, ajouter un composant (uniquement des data) à une entité (uniquement un id) lui ajoute de la fonctionnalité via les systèmes (uniquement de l'implémentation).

    Cette découpe est non seulement pratique d'un point de vue maintenance du code, mais en plus, elle scale bien.

    Et si on reprend l'exemple de la POO dans le monde des entreprises, avec les dizaines de couche d'abstraction pour faire un print, les librairies qui font plus que leur scope initiale (coucou log4shell), ça ne scale pas. On se retrouve 10 ans plus tard avec un monolithe qui mets 45min a build un simple commit.

    J'ai même envie de faire le parallèle avec l'infrastructure. Aujourd'hui, les microservices sont au centre d'une grosse hype. L'idée étant d'avoir des briques élémentaires (fonctions, microservices, …) que tu assembles comme des Lego pour construire un système complexe.

    Alors oui, les microservices ne répondent que a un problème organisationnel de l'entreprise (comment plusieurs teams peuvent bosser sur le même projet sans se marcher dessus ?), j'ai envie de dire que la programmation fonctionnelle répond à un problème organisationnel du code source (comment plusieurs systèmes peuvent fonctionner en parallèle sans fuite de l'API et avec une bonne "Separation of Concerns").

    L'autre raison que je vois à la popularité de la programmation fonctionnelle, c'est :

    • React/Redux et ses successeurs, dont l'architecture est purement fonctionnelle (l'UI est une fonction qui prend en paramètre le state)

    Le plus marrant je trouve la dedans, c'est que la montée en popularité de la programmation fonctionnelle a lieu surtout dans des langages qui ne sont pas fonctionnels :

    Alors qu'il y a OCaml, Elixir, Haskell, Purescript (si tu veux compiler en du Haskell en JS), etc…

    https://link-society.com - https://kubirds.com - https://github.com/link-society/flowg

    • [^] # Re: J'ai pas écouté le podcast, mais mon grain de sel

      Posté par  . Évalué à 3. Dernière modification le 12 mars 2022 à 15:40.

      Sauf que POO et Programmation Fonctionnelle ne sont pas incompatible. Prenons l'exemple de Go

      C'est quand même ballot de prendre comme exemple un langage qui n'est ni objet, ni fonctionnel… Alors que des langages fonctionnels et objet, tu en as à la pelle, par exemple Lisp (avec CLOS), OCaml, Kotlin, …

      • [^] # Re: J'ai pas écouté le podcast, mais mon grain de sel

        Posté par  (site web personnel) . Évalué à 6.

        En Go, tu peux passer des fonctions en argument à d'autres, ce qui implique que tu as des fonctions d'ordre supérieur. Avec les generics de Go 1.18 on voit apparaître des patterns typique de la programmation fonctionnelle (cf les 2 liens que j'ai cité avec l'implémentation des map/filter/reduce/…).

        La POO c'est le concept d'encapsulation des données pour présenter une API (les méthodes) pour les manipuler. A ce que je sache, Go permet cela avec les structures et les fonctions qui prennent un paramètre "receiver".

        De plus, les interfaces de Go permettent d'avoir du polymorphisme.

        La programmation fonctionnelle, c'est l'art d'organiser son code autour de fonctions, de closures, et de combinators. Toutes ces choses sont possible en Go.

        Tu peux aussi faire de la POO en C : https://www.cs.rit.edu/~ats/books/ooc.pdf

        C'est quand même ballot de prendre comme exemple un langage qui n'est ni objet, ni fonctionnel…

        Pas si ballot que ça du coup, vu que c'est le parfait exemple d'un langage qui permet de marier les 2 concepts.

        https://link-society.com - https://kubirds.com - https://github.com/link-society/flowg

        • [^] # Re: J'ai pas écouté le podcast, mais mon grain de sel

          Posté par  . Évalué à 1.

          C’est aussi le cas en javascript, les fonctions d’ordre supérieur et à la base quasi tout basé sur les fonctions, je comprends pas pourquoi tu l’as exclu des langages fonctionnels du coup.

          • [^] # Re: J'ai pas écouté le podcast, mais mon grain de sel

            Posté par  (site web personnel) . Évalué à 3.

            Parce que je fais la différence entre :

            • langage objet et programmation orientée objet
            • langage fonctionnel et programmation fonctionnelle

            Dans un langage objet, tout est objet, tu n'as pas de type primitifs (1 et true et "hello" sont des objets, pas des valeurs primitives).

            Dans un langage fonctionnel, les données sont immutables et les fonctions sont des données.

            En Javascript, tu ne peux pas passer une fonction en tant que valeur à un Worker (thread/process) par exemple. Ce qui veut dire que la fonction n'est pas une valeur. Ce n'est donc pas un langage fonctionnel.

            Toujours en Javascript, 1 n'est pas un objet, ce n'est donc pas un langage objet.

            Cela n'empêche pas d'appliquer du mieux qu'on peut les concepts de ces 2 paradigmes.

            A ma connaissance, seul Smalltalk est un vrai langage objet (le code en lui même est un objet que tu peux manipuler).

            Concernant les langages fonctionnels, on va identifier 2 types :

            • purement fonctionnel (les effets de bords sont abstrait par le runtime) : Haskell / Purescript
            • les autres : Erlang / Elixir

            Et donc par cette définition, non ni Javascript, ni Go, ni Python, ni C++, ni beaucoup de langages ne sont "objets" ou "fonctionnels". Ultimement tout ces langages se retrouvent exécuté par un CPU, donc représenté d'une manière ou d'une autre par une suite d'instruction assembleur. Donc a partir du moment ou ton langage est Turing-Complete, tu peux réutiliser ces paradigmes.

            https://link-society.com - https://kubirds.com - https://github.com/link-society/flowg

            • [^] # Re: J'ai pas écouté le podcast, mais mon grain de sel

              Posté par  (Mastodon) . Évalué à 2.

              A ma connaissance, seul Smalltalk est un vrai langage objet (le code en lui même est un objet que tu peux manipuler).

              Je ne connais pas mais j'ai lu que dans Ruby aussi tout était objet.

              Surtout, ne pas tout prendre au sérieux !

            • [^] # Re: J'ai pas écouté le podcast, mais mon grain de sel

              Posté par  . Évalué à 3.

              En Javascript, tu ne peux pas passer une fonction en tant que valeur à un Worker (thread/process) par exemple. Ce qui veut dire que la fonction n'est pas une valeur. Ce n'est donc pas un langage fonctionnel.

              Les fonctions sont des « first-class citizens » en javascript, tu peux affecter une fonction à n’importe quelle variable. C’est la définition. Que les workers fonctionnent autrement c’est un autre problème non ? C’est un moyen de faire du parallélisme qui limite les possibilités de communication, sûrement à cause de la non pureté du langage. Si ce n’est pas fonctionnel, ça voudrait dire qu’avant l’introduction des Workers ça l’était et que ça ne l’est plus désormais ? C’est étrange.

              Le plus vieux langage considéré comme pur est lisp il me semble, qui n’est pas pur si je ne m’abuse.

              • [^] # Re: J'ai pas écouté le podcast, mais mon grain de sel

                Posté par  (site web personnel) . Évalué à 4.

                Tu ne peux pas copier une fonction avec sa scope, juste la passer par référence.

                Et tu n'as jamais pu le faire. Les Worker sont l'exemple parfait du fait que tu ne puisse pas copier une fonction.

                C'est comme en C, tu as des pointeurs de fonctions, que tu peux copier, mais pas la fonction en elle même.

                En Erlang / Elixir, tu as 2 types de fonctions :

                • les fonctions anonymes, qui peuvent être copiée et stockée dans un ETS/DETS/Mnesia, envoyé a un autre node du cluster pour être exécutée la bas, AVEC sa scope
                • les fonctions définies dans un module, et la tu les "copie" en passant le tuple {Module, Function, Arguments} ou Module et Function sont des atoms.

                Alors oui, assigner une fonction (sa référence) à une variable te permet d'avoir des fonctions d'ordre supérieur et de faire de la programmation fonctionnelle, mais non ça ne fait pas de ton langage un langage fonctionnel.

                https://link-society.com - https://kubirds.com - https://github.com/link-society/flowg

                • [^] # Re: J'ai pas écouté le podcast, mais mon grain de sel

                  Posté par  . Évalué à 3. Dernière modification le 13 mars 2022 à 09:54.

                  Ok je vois c'est parce que c'est impossible de faire des "copies profondes" dans le jargon JS de clôtures par exemple.

                  Du coup c'est l'impossibilité d'eviter les effets de bord. Quand on le veut.

              • [^] # Re: J'ai pas écouté le podcast, mais mon grain de sel

                Posté par  (site web personnel, Mastodon) . Évalué à 2.

                Le plus vieux langage considéré comme pur est lisp il me semble, qui n’est pas pur si je ne m’abuse.

                Pas compris : c'est quoi « considéré comme pur » et selon quels critères ?
                Tu veux dire que ce n'est pas un langage fonctionnel pur comme dit dans le message auquel tu réponds ? Pourtant il en a tous les critères (et c'était le premier langage qui pouvait se manipuler lui-même, et à ne pas distinguer les données du code.)

                “It is seldom that liberty of any kind is lost all at once.” ― David Hume

              • [^] # Re: J'ai pas écouté le podcast, mais mon grain de sel

                Posté par  . Évalué à -1.

                actuellement aucun langage, fonctionnel ou pas ne permet de passer une fonction par valeur. Cela revient à recopier le binaire associé à la fonction. Si d'aventure un langage le permet, je suis preneur.

                • [^] # Re: J'ai pas écouté le podcast, mais mon grain de sel

                  Posté par  . Évalué à 3.

                  Si la fonction est pure, soit sans effet de bord, recopier son code ou une référence revient au même.

                  Sur ma HP48, on pouvait manipuler le code directement dans la pile, manipuler l’ordre des éléments, les dupliquer, les évaluer, les concaténer, etc.

                  Dans tous les cas, il va rester le problème des variables globales et des effets de bord, qu’il y ait copie ou non.

                  • [^] # Re: J'ai pas écouté le podcast, mais mon grain de sel

                    Posté par  . Évalué à 1.

                    évidemment si le langage est interprété, il n'y a pas de problème. J'ai crée quelques Forth pour du temps réel. Si cela était possible avec un langage compilé, le concept de machine virtuelle n'aurait pas de sens.

                    • [^] # Re: J'ai pas écouté le podcast, mais mon grain de sel

                      Posté par  . Évalué à 2.

                      Le langage n’était pas vraiment interprété. Un programme était constitué d’une liste d’objets. Un objet pouvez être un nombre, une instruction, un programme.
                      Les 5 premiers quartets (2,5 octets) de l’objet étaient un pointeur vers le code assembleur gérant l’objet. Par exemple pour un nombre, c’était d’ajouter le nombre dans la pile. Pour un +, le code prend les deux nombres dans la pile, les ajoutes et recrée un objet de nombre dans la pile.
                      La fin du code assembleur d’un objet termine toujours par une instruction JUMP vers le pointeur de l’objet suivant.

                      Dans les objets faits par HP, il y en avait deux un peu spéciaux : begin et end qui permettait d’agréger des objets pour faire un truc de plus haut niveau. J’ai trouvé cette façon de faire vraiment très élégante.

      • [^] # Re: J'ai pas écouté le podcast, mais mon grain de sel

        Posté par  (site web personnel, Mastodon) . Évalué à 3.

        Bof, quand tu as compris le principe tu peux l'implémenter en assembleur ou n'importe quel langage impératif. Faire du fonctionnel ou de l'orienté objet ne doit pas se réduire à utiliser un langage qui offrirait des outils pour le paradigme (sinon on obtient des trucs comme, déjà vu, des gens qui font du C à l'ancienne et disent faire de l'objet parce-que compilant avec C++ ou ObjectiveC ou C# ou etc.)
        Je trouve génial la réponse qui s'appuie sur un langage assez connu mais qui ne fait pas tomber dans les biais induis par les langages dédiés : le lectorat est obligé de s'accrocher aux concepts et à leur mise en œuvre et non de suivre la pente d'un langage facilitant (et sa syntaxe.)

        “It is seldom that liberty of any kind is lost all at once.” ― David Hume

  • # Betteridge

    Posté par  . Évalué à 6.

    « À tout titre d'article journalistique se terminant par un point d'interrogation il peut être répondu par la négative »

    • [^] # Re: Betteridge

      Posté par  (site web personnel, Mastodon) . Évalué à -3.

      Le point d'interrogation étant une interrogation on devrait pouvoir plusieurs réponses… aussi bien la négative que la positive.

      “It is seldom that liberty of any kind is lost all at once.” ― David Hume

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.