J'entends beaucoup sur les langages fonctionnelles et comment ils échouent bien car il n'y a pas d'état autour d'une fonction; et donc cette fonction peut être massivement parallélémentaire. p>
Cependant, cela me semble peu logique parce que presque tous les programmes pratiques du monde réel ont besoin / ont un État à prendre en charge. Je trouve également intéressant que la plupart des grandes bibliothèques de mise à l'échelle, c'est-à-dire mapreduce, sont généralement écrites dans des langages impératifs tels que C ou C ++. P>
J'aimerais entendre le camp fonctionnel où ce battage médiatique que j'entends vient de .. p>
5 Réponses :
Des langues fonctionnelles telles que Haskell, Scheme et d'autres sont appelées "fonctions pures". Une fonction pure est une fonction sans effets secondaires. Cela ne modifie aucun autre état dans le programme. Ceci est par définition threadsafe. P>
Bien sûr, vous pouvez écrire des fonctions pures en langues impératives. Vous trouverez également des langages multi-paradigmes comme Python, Ruby et même C # où vous pouvez faire une programmation impérative, une programmation fonctionnelle ou des deux. P>
mais le point de haskell (etc.) est que vous ne pouvez pas em> écrire une fonction non pure. Eh bien que ce n'est pas strictement vrai, mais c'est surtout vrai. P>
De même, de nombreuses langues impératives ont des objets immuables pour la même raison. Un objet immuable est celui dont l'état ne change pas une fois créé. Encore une fois par définition, un objet immuable est Threadsafe. P>
Oui, mais vous pourriez aussi faire cela avec des langues impératives ... D'où ma confusion. Ce n'est pas comme si l'analyse statique d'une telle chose est difficile.
Vous parlez de deux choses différentes et ne le réalisez pas. P>
Oui, la plupart des programmes du monde réel ont un État quelque part em>, mais si vous voulez faire de multithreading, cet État ne devrait pas être partout em>, et en fait, moins les lieux C'est dans, mieux c'est. Dans les programmes fonctionnels, la valeur par défaut ne doit pas avoir d'état, et vous pouvez introduire l'état exactement où vous en avez besoin et nulle part ailleurs. Ces pièces qui traitent de l'État ne seront pas aussi facilement multithreadées, mais que tout le reste de votre programme est exempte d'effets secondaires et que cela n'a pas d'importance dans ce que les pièces sont exécutées, elle supprime une énorme barrière à la parallélisation. . p>
Vous dites donc que c'est plus sur le style de programmation que de la langue elle-même?
@Billy Oneal - C'est beaucoup plus que le style de programmation. FP retourne le modèle de programmation sur. En impératif, la plupart de tout est mutable par défaut et vous devez faire des efforts supplémentaires pour éviter les mutations. Dans la FP, la plupart de tout est immuable par défaut et vous devez faire un effort pour rendre quelque chose de mutable. C'est un changement de pensée et d'approche de 180 degrés.
@Billy Oneal: Dans une large mesure, il s'agit d'un style de programmation, mais une langue peut vraiment affecter votre style de programmation. L'avantage des langues fonctionnelles est qu'ils soutiennent très bien ce style de programmation. Les choses qui sont naturelles dans les langues fonctionnelles sont plus maladroites dans des langues impératives et inversement. Il existe également des avantages supplémentaires aux langues fonctionnelles qui enlèvent de cela, telles que la STM étant morte facile, lorsque certaines parties de votre programme sont garanties i> de ne pas avoir d'effets secondaires.
@CHUCK: Qu'est-ce que la STM? @ONorio CATENACCCI: Les compilateurs tiennent déjà compte de telles choses lorsque vous faites des choses comme faire des décisions d'inliction. Je ne pense pas que de telles choses sont extrêmement importantes d'un point de vue de la performance.
@Billy: Mémoire transactionnelle logicielle
@Billy Oneal, je pense que vous faites une hypothèse potentiellement dangereuse sur la manière dont les compilateurs optimisent le code dans ces cas. Et Chuck a raison - écrire un code immuable dans une langue impérative peut être beaucoup plus complexe et donc difficile pour un autre développeur à suivre plus tard. Code C ou C ++ qui utilise des pointeurs de la fonction dans une large mesure sans Typedef? Cela peut être joliment velu à suivre.
@Onorio Catenacci: Euh .. Ouais. C'est pourquoi nous avons des typées.
@ Billy - J'ai pointé des pointeurs de fonction comme exemple de quelque chose que FP rend beaucoup plus simple. Au fond, tout est traduit en montage, il est tout simplement que la FP le rend un peu plus facile pour les êtres humains qui doivent lire le code plus tard. À un moment donné, ce n'est pas une question de ce qui est théoriquement possible; C'est une question de ce qui se passe dans la pratique. Un développeur pourrait écrire du code C / C ++ de manière fonctionnelle et permet de sauvegarder toutes sortes de problèmes avec la sécurité du fil. Mais ce n'est pas ce qui se passera dans la pratique pour un certain nombre de raisons: des délais, des idiomes de codage acceptés, etc.
À titre d'exemple de la manière dont un programme Rare A C ++ écrit dans le style fonctionnel est le suivant: combien de programmes C ++ avez-vous vu qui déclara presque toutes les variables const code>? À peu près jamais, je pariéais. Pourtant, ce genre de chose est fait tout le temps dans les langues fonctionnelles.
@Chuck: Quoi? Const code> Correction des mandats que toutes les variables pouvant être const code> sont const code>. Un développeur C ++ qui ne fait pas qui est un mauvais développeur C ++.
@Billy: Ce n'est pas ma compréhension, et ce n'est pas la façon dont la plupart du code C ++ j'ai vu des œuvres. Const-Cidressness charge que les variables que vous veulent i> constantes sont constantes sont const code>, pour encoder cette contrainte dans votre programme. Cela ne nécessite pas que vous concevez votre programme pour éviter l'état mutable.
@CHUCK: Vous devriez WANT I> quelque chose à être constant qui peut être constant. Pourquoi le rendre mutable quand il peut être constant?
Fonctions d'ordre supérieur. Considérez une opération de réduction simple, en sommant les éléments d'un tableau. Dans une langue impérative, les programmeurs se écrivent généralement une boucle et effectuent des réductions un élément à la fois. P>
Mais ce code n'est pas facile de faire plusieurs filetés. Lorsque vous écrivez une boucle, vous supposez une commande d'opérations et vous devez épeler comment obtenir un élément à l'autre. Vous aimeriez vraiment dire simplement «Sum à la matrice» et avoir le compilateur, ou l'exécution du temps, ou tout ce que vous décidez de travailler à travers la matrice, de diviser la tâche si nécessaire entre plusieurs cœurs et de combiner ces résultats ensemble . Donc, au lieu d'écrire une boucle, avec un code d'addition incorporé à l'intérieur, une alternative consiste à réussir quelque chose représentant "addition" dans une fonction qui peut faire la division. Dès que vous le faites, vous écrivez fonctionnellement. Vous passez une fonction (addition) dans une autre fonction (le réducteur). Si vous écrivez de cette façon, cela fait non seulement un code plus lisible, mais lorsque vous changez d'architecture ou que vous souhaitez écrire pour une architecture hétérogène, vous n'avez pas à changer l'été, ce n'est que le réducteur. En pratique, vous pourriez avoir de nombreux algorithmes différents que tous partagent un réducteur, il s'agit donc d'un grand gain. P>
Ceci est juste un exemple simple. Vous voudrez peut-être construire sur ceci. Fonctions Pour appliquer d'autres fonctions sur des matrices 2D, des fonctions permettant d'appliquer des fonctions aux structures d'arborescences, des fonctions permettant de combiner des fonctions pour appliquer des fonctions (par exemple, si vous avez une structure hiérarchique avec des arbres ci-dessus et des tableaux ci-dessous) et ainsi de suite. P>
Oui, je comprends ça. Mais il y a beaucoup de façons de gérer ce problème dans des langues impératives aussi - c'est-à-dire des piscines de fil. Oui, vous écrivez la fonctionnalité, mais je ne vois pas comment cela est différent dans des langues fonctionnelles autres que "quelqu'un a déjà écrit ce peu de fonctionnalité pour moi"
Non, c'est complètement orthogonal pour filer des piscines. Je ne parle pas du code pour gérer les threads, mais l'interface. La façon dont vous lancez une opération code> code> est de transmettre une fonction comme argument. C'est la programmation fonctionnelle. Mapreduce est fonctionnel. Il faut deux arguments, une fonction de carte et une fonction de réduction. Les fonctions qui agissent sur les fonctions sont appelées fonctions d'ordre supérieur. C'est ce qu'est la programmation fonctionnelle.
Cependant, cela a peu de sens pour moi parce que presque tout le monde réel Les programmes pratiques ont besoin / ont un État à prendre en charge. P> blockQuote>
Vous seriez surpris! Oui, tous les programmes ont besoin d'un État (E / S en particulier), mais souvent, vous n'avez pas besoin de beaucoup plus. Juste parce que la plupart des programmes ont des tas d'État ne signifie pas qu'ils ont besoin em> it. P>
La programmation dans une langue fonctionnelle vous encourage à utiliser moins d'état et que vos programmes deviennent donc plus faciles à paralLier. p>
De nombreuses langues fonctionnelles sont "impur", ce qui signifie qu'ils permettent certains em> état. Haskell ne le fait pas, mais Haskell a des monades qui vous permettent d'obtenir quelque chose de rien: vous obtenez l'état à l'aide de constructions apatrides. Les monades sont un peu fidèles à travailler avec lesquelles Haskell vous donne une forte incitation à restreindre l'état aussi petit que possible de votre programme. P>
Je trouve également intéressant que la plupart des bibliothèques d'échelle majeures, c'est-à-dire Mapreduce, sont généralement écrits dans des langages impératifs tels que C ou C ++. P> blockQuote>
La programmation Les applications simultanées sont "difficiles" en C / C ++. C'est pourquoi il est préférable de faire toutes les choses dangereuses dans une bibliothèque qui est fortement testée et inspectée. Mais vous obtenez toujours la flexibilité et la performance de C / C ++. P>
Je pense à des choses comme en.wikipedia.org/wiki/dijkstra's_algorithme . Disons que je veux écrire une application massivement parallèle pour trouver le moyen le plus court de mapper quelqu'un du point A au point B. dijkstra's_algorithm repose sur une file d'attente. Alors que dans Theroyy, vous pouvez parallementer des morceaux de l'algorithme, il reste toujours le morceau d'état - une file d'attente - qui est partagée et requise pour que l'algorithme fonctionne. Tel est le cas pour chaque algorithme de programmation dynamique et de tels algorithmes sont nécessaires pour rendre certaines choses efficaces.
Certainement - les langues fonctionnelles ne sont pas une balle d'argent. Parfois, la réponse est d'utiliser un algorithme nominalement moins efficace, mais plus facile à paralleraliser (par exemple un algorithme pouvant être facilement exprimé dans une langue fonctionnelle), vous permettant ainsi de résoudre un problème plus rapidement. D'autres fois, vous devez construire les trucs simultanés manuellement [en C / C ++ / Peu importe]. Mais cela peut être une bonne stratégie pour utiliser des langues fonctionnelles dans la mesure du possible et de recourir à d'autres options lorsqu'il est nécessaire.
Il est important d'ajouter un mot: "Il n'y a pas partagé STRY> Etat". p>
Tout programme significatif (dans n'importe quelle langue) change l'état du monde. Mais (certaines) langues fonctionnelles empêchent d'accéder simultanément à la même ressource de plusieurs threads. L'absence d'état fort> partagé fort> est en sécurité multithreading. P>
J'avais évoqué que les bibliothèques de mise à l'échelle ne sont pas écrites en C / C ++, car elles sont bien adaptées au problème ... plutôt qu'il est possible d'écrire plus de code performant.
@Spender: J'accepterais que c'est une sorte de duplicata. Cependant, toutes les réponses à cette question disent essentiellement «Eh bien, c'est parce que dans des programmes fonctionnels que vous n'avez pas d'état mutable». Cette question est posée "Comment vous rapprochez-vous l'immuabilité avec la modélisation des problèmes du monde réel, qui nécessite généralement au moins un État mutable» (OK, ce qui n'est pas énoncé explicitement dans cette question, mais je pense que c'est ce qui est impliqué par la manière dont il est impliqué expulsé; Je pourrais très bien avoir tort). Je ne pense pas que les réponses à l'autre question répondent à cette partie de manière satisfaisante.
Je suis peut-être fou, mais ma compréhension est qu'elle est plus difficile de faire "la mauvaise chose" dans les langues fonctionnelles, de sorte que l'attente est que si les personnes codées dans des langues fonctionnelles, le code serait magiquement le fil de sécurité. Mon principe est que les gens qui veulent un État mondial (ou autrement disponible) feront tout ce qu'il faut pour l'obtenir, quelle que soit la langue. Il est complètement possible de coder même en C ++ dans un style fonctionnel. Le problème n'est pas la langue (sinon "les outils"), ce sont les programmeurs ("les utilisateurs").
Multi-noyau! = Multithreading. Ils sont deux choses différentes. Le multithreading est toujours pertinent sur un seul processeur de base pour un.
@Cletus: Oui, mais il n'y a pas de différence à partir du potentiel d'un programmeur. Et je parle de plus d'un fil d'exécution simultané en termes généraux plutôt que d'une configuration matérielle spécifique.
@Billy pas vrai. Prenez Python comme exemple. Un programme singuléthraté sur une machine à base unique peut être différent d'un programme singulé sur un programme multicœur (avec des tâches liées à la CPU sur CPPHON grâce à la GIL). Les termes ne sont pas interchangeables.
@CLETUS: Je parle de plusieurs threads pouvant figurer sur des machines physiques distinctes, pas nécessairement dans le contexte d'une seule machine. Je parle de multiples threads simultanés d'exécution, pas nécessairement sur les processeurs multi-coreaux. Par conséquent, j'ai choisi la multithreading plutôt que multi-noyau.
J'ai répondu à votre question ici Stackoverflow.com/questions/181284/ ... Veuillez mal comprendre, ce sont des questions différentes.
@Spender, cette question pose pourquoi les langues fonctionnelles sont meilleures lors de la rédaction de programmes sans modification de l'état. L'autre question pose pourquoi les langues fonctionnelles sont bonnes pour une programmation simultanée. Les réponses sont différentes. S'il vous plaît mal de mallette.
Ce serait si grand si quelqu'un a donné un exemple avec code.